{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:03.045285Z",
     "start_time": "2021-04-30T19:52:03.026767Z"
    }
   },
   "outputs": [],
   "source": [
    "from IPython.core.display import HTML\n",
    "HTML(open(\"custom.css\", \"r\").read())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "toc": true
   },
   "source": [
    "<h1>Table of Contents<span class=\"tocSkip\"></span></h1>\n",
    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#From-Transistors-to-ALUs-With-Skywater\" data-toc-modified-id=\"From-Transistors-to-ALUs-With-Skywater-1\">From Transistors to ALUs With Skywater</a></span><ul class=\"toc-item\"><li><span><a href=\"#Installing-Some-Tools\" data-toc-modified-id=\"Installing-Some-Tools-1.1\">Installing Some Tools</a></span></li><li><span><a href=\"#Getting-the-Skywater-PDK\" data-toc-modified-id=\"Getting-the-Skywater-PDK-1.2\">Getting the Skywater PDK</a></span></li><li><span><a href=\"#Some-Infrastructure\" data-toc-modified-id=\"Some-Infrastructure-1.3\">Some Infrastructure</a></span></li><li><span><a href=\"#The-Simplest:-the-Inverter\" data-toc-modified-id=\"The-Simplest:-the-Inverter-1.4\">The Simplest: the Inverter</a></span></li><li><span><a href=\"#The-Universal:-the-NAND-Gate\" data-toc-modified-id=\"The-Universal:-the-NAND-Gate-1.5\">The Universal: the NAND Gate</a></span></li><li><span><a href=\"#One-or-the-Other:-the-XOR-Gate\" data-toc-modified-id=\"One-or-the-Other:-the-XOR-Gate-1.6\">One or the Other: the XOR Gate</a></span></li><li><span><a href=\"#No,-It's-Not-a-Snake:-The-Adder\" data-toc-modified-id=\"No,-It's-Not-a-Snake:-The-Adder-1.7\">No, It's Not a Snake: The Adder</a></span></li><li><span><a href=\"#Fragments-of-Memory:-Latches,-Flip-Flops-and-Registers\" data-toc-modified-id=\"Fragments-of-Memory:-Latches,-Flip-Flops-and-Registers-1.8\">Fragments of Memory: Latches, Flip-Flops and Registers</a></span></li><li><span><a href=\"#The-Simplest-State-Machine:-the-Counter\" data-toc-modified-id=\"The-Simplest-State-Machine:-the-Counter-1.9\">The Simplest State Machine: the Counter</a></span></li><li><span><a href=\"#Bonus:-an-ALU\" data-toc-modified-id=\"Bonus:-an-ALU-1.10\">Bonus: an ALU</a></span></li><li><span><a href=\"#Extra-Bonus:-a-Down-Counter\" data-toc-modified-id=\"Extra-Bonus:-a-Down-Counter-1.11\">Extra Bonus: a Down Counter</a></span></li><li><span><a href=\"#End-of-the-Line\" data-toc-modified-id=\"End-of-the-Line-1.12\">End of the Line</a></span></li></ul></li></ul></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# From Transistors to ALUs With Skywater\n",
    "\n",
    "[Google and SkyWater Technology](https://woset-workshop.github.io/PDFs/2020/a03.pdf) are cooperating to provide open-source hardware designers with a way to build custom ASICs. Part of this effort is the release of the [SkyWater PDK](https://github.com/google/skywater-pdk) which describes the parameters for a 130nm CMOS process. I thought it might be fun to simulate a few logic gates in SPICE using this PDK."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Installing Some Tools\n",
    "\n",
    "[This repo](https://github.com/bluecmd/learn-sky130/blob/main/schematic/xschem/getting-started.md) provided some guidance when I first started investigating the PDK, but it uses external tools like [XSCHEM](http://repo.hu/projects/xschem/) (for schematic capture) and [GAW](https://gaw.tuxfamily.org/linux/gaw.php) (for displaying waveforms). To make my work easier to replicate and distribute, I wanted everything to be done in a Jupyter notebook. It wasn't immediately apparent how I would integrate XSCHEM/GAW into a notebook and [schematics shouldn't be used in polite company](https://www.youtube.com/watch?v=WErQYI2A36M&list=PLy2022BX6EsqLkQy1EmXjVnauOH3FSHTV&index=3&t=257s) any way, so I took a more Python-centric approach and used these tools:\n",
    "\n",
    "* [ngspice](http://ngspice.sourceforge.net/): An open-source SPICE simulator.\n",
    "* [SciPy bundle](https://www.scipy.org/index.html): General-purpose Python libraries for handling data.\n",
    "* [SKiDL](https://github.com/xesscorp/skidl): Used to describe circuitry using Python code.\n",
    "* [PySpice](https://github.com/FabriceSalvaire/PySpice): A Python interface between SKiDL and ngspice.\n",
    "\n",
    "Pre-built versions of ngspice are available for Windows and MacOS. For linux, I got the latest ngspice files (version 33) from [here](https://sourceforge.net/projects/ngspice/files/ng-spice-rework/33/), unpacked it into the `ngspice-33` directory, and built it using the instructions in the INSTALL file:\n",
    "\n",
    "```bash\n",
    "$ cd ngspice-33\n",
    "$ mkdir release\n",
    "$ cd release\n",
    "$ ../configure --with-x --enable-xspice --disable-debug --enable-cider --with-readline=yes --enable-openmp\n",
    "$ make 2>&1 | tee make.log\n",
    "$ sudo make install\n",
    "```\n",
    "\n",
    "Installing the SciPy tools was also easy since I already had Python:\n",
    "```bash\n",
    "$ pip install matplotlib numpy pandas jupyter \n",
    "```\n",
    "\n",
    "I couldn't use the PyPi versions of PySpice and SKiDL because they had to be modified to make them work with the Skywater PDK. If you want to run this notebook, you'll need to install the development versions of those from GitHub:\n",
    "\n",
    "```bash\n",
    "$ pip install git+https://github.com/xesscorp/PySpice\n",
    "$ pip install git+https://github.com/xesscorp/skidl@development\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once all these tools were installed, I imported them into this notebook:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:03.977351Z",
     "start_time": "2021-04-30T19:52:03.047948Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: KICAD_SYMBOL_DIR environment variable is missing, so the default KiCad symbol libraries won't be searched.\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd              # For data frames.\n",
    "import matplotlib.pyplot as plt  # For plotting.\n",
    "from skidl.pyspice import *      # For describing circuits and interfacing to ngspice."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting the Skywater PDK\n",
    "\n",
    "With the tooling in place, it was time to get the Skywater PDK. If I wanted to wait a *long time*, I could install the entire PDK like this:\n",
    "```bash\n",
    "$ git clone --recurse-submodules https://github.com/google/skywater-pdk\n",
    "```\n",
    "\n",
    "But I don't need *everything*, just the latest SPICE models for the device primitives, so the following command is much quicker: \n",
    "\n",
    "```bash\n",
    "$ git clone --recurse-submodules=libraries/sky130_fd_pr/latest https://github.com/google/skywater-pdk\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Even with a stripped-down repo, there's a lot of stuff in there. The [Skywater documentation](https://skywater-pdk.readthedocs.io/en/latest/index.html) provides some guidance, but there are a lot of sections that just contain **TODO**. Poking about in the PDK led me to these directories of device information files as decribed [here](https://skywater-pdk.readthedocs.io/en/latest/rules/device-details.html):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:04.144561Z",
     "start_time": "2021-04-30T19:52:03.981176Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cap_mim_m3/\t\t\t\t      esd_rf_diode_pd2nw_11v0/\r\n",
      "cap_var_hvt/\t\t\t\t      esd_rf_diode_pw2nd_11v0/\r\n",
      "cap_var_lvt/\t\t\t\t      esd_rf_nfet_20v0_hbm/\r\n",
      "cap_vpp_01p8x01p8_m1m2_noshield/\t      esd_rf_nfet_20v0_iec/\r\n",
      "cap_vpp_02p4x04p6_m1m2_noshield/\t      ind_03/\r\n",
      "cap_vpp_02p7x06p1_m1m2m3m4_shieldl1/\t      ind_05/\r\n",
      "cap_vpp_02p7x11p1_m1m2m3m4_shieldl1/\t      nfet_01v8/\r\n",
      "cap_vpp_02p7x21p1_m1m2m3m4_shieldl1/\t      nfet_01v8_lvt/\r\n",
      "cap_vpp_02p7x41p1_m1m2m3m4_shieldl1/\t      nfet_03v3_nvt/\r\n",
      "cap_vpp_02p9x06p1_m1m2m3m4_shieldl1/\t      nfet_05v0_nvt/\r\n",
      "cap_vpp_03p9x03p9_m1m2_shieldl1_floatm3/      nfet_20v0/\r\n",
      "cap_vpp_04p4x04p6_l1m1m2_noshield/\t      nfet_20v0_iso/\r\n",
      "cap_vpp_04p4x04p6_l1m1m2_shieldpo_floatm3/    nfet_20v0_nvt/\r\n",
      "cap_vpp_04p4x04p6_m1m2m3_shieldl1/\t      nfet_20v0_nvt_iso/\r\n",
      "cap_vpp_04p4x04p6_m1m2m3_shieldl1m5_floatm4/  nfet_20v0_reverse_iso/\r\n",
      "cap_vpp_04p4x04p6_m1m2_noshield/\t      nfet_20v0_zvt/\r\n",
      "cap_vpp_04p4x04p6_m1m2_shieldl1/\t      nfet_g5v0d10v5/\r\n",
      "cap_vpp_05p9x05p9_m1m2m3m4_shieldl1/\t      nfet_g5v0d16v0/\r\n",
      "cap_vpp_06p8x06p1_l1m1m2m3_shieldpom4/\t      npn_05v5/\r\n",
      "cap_vpp_06p8x06p1_m1m2m3_shieldl1m4/\t      npn_11v0/\r\n",
      "cap_vpp_08p6x07p8_l1m1m2_noshield/\t      nwdiode_top/\r\n",
      "cap_vpp_08p6x07p8_l1m1m2_shieldpo_floatm3/    pfet_01v8/\r\n",
      "cap_vpp_08p6x07p8_m1m2m3_shieldl1/\t      pfet_01v8_hvt/\r\n",
      "cap_vpp_08p6x07p8_m1m2m3_shieldl1m5_floatm4/  pfet_01v8_lvt/\r\n",
      "cap_vpp_08p6x07p8_m1m2_noshield/\t      pfet_01v8_mvt/\r\n",
      "cap_vpp_08p6x07p8_m1m2_shieldl1/\t      pfet_20v0/\r\n",
      "cap_vpp_11p3x11p3_m1m2m3m4_shieldl1/\t      pfet_g5v0d10v5/\r\n",
      "cap_vpp_11p3x11p8_l1m1m2m3m4_shieldm5/\t      pfet_g5v0d16v0/\r\n",
      "cap_vpp_11p5x11p7_l1m1m2m3m4_shieldm5/\t      pnp_05v5/\r\n",
      "cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5/      res_generic_nd/\r\n",
      "cap_vpp_11p5x11p7_l1m1m2m3_shieldm4/\t      res_generic_pd/\r\n",
      "cap_vpp_11p5x11p7_l1m1m2m3_shieldpom4/\t      res_high_po/\r\n",
      "cap_vpp_11p5x11p7_l1m1m2_noshield/\t      res_iso_pw/\r\n",
      "cap_vpp_11p5x11p7_l1m1m2_shieldpom3/\t      res_xhigh_po/\r\n",
      "cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5/\t      rf_aura_blocking/\r\n",
      "cap_vpp_11p5x11p7_m1m2m3m4_shieldm5/\t      rf_aura_drc_flag_check/\r\n",
      "cap_vpp_11p5x11p7_m1m2m3_shieldl1/\t      rf_aura_lvs_drc/\r\n",
      "cap_vpp_11p5x11p7_m1m2m3_shieldl1m5_floatm4/  rf_nfet_01v8/\r\n",
      "cap_vpp_11p5x11p7_m1m2_noshield/\t      rf_nfet_01v8_lvt/\r\n",
      "cap_vpp_11p5x11p7_m1m2_shieldl1/\t      rf_nfet_20v0_aup/\r\n",
      "cap_vpp_11p5x11p7_m1m4_noshield/\t      rf_nfet_20v0_noptap_iso/\r\n",
      "cap_vpp_11p5x11p7_pol1m1m2m3m4m5_noshield/    rf_nfet_20v0_nvt_aup/\r\n",
      "cap_vpp_11p5x23p1_pol1m1m2m3m4m5_noshield/    rf_nfet_20v0_nvt_noptap_iso/\r\n",
      "cap_vpp_22p5x11p7_pol1m1m2m3m4m5_noshield/    rf_nfet_20v0_nvt_withptap/\r\n",
      "cap_vpp_22p5x23p1_pol1m1m2m3m4m5_noshield/    rf_nfet_20v0_nvt_withptap_iso/\r\n",
      "cap_vpp_33p6x11p7_pol1m1m2m3m4m5_noshield/    rf_nfet_20v0_withptap/\r\n",
      "cap_vpp_33p6x23p1_pol1m1m2m3m4m5_noshield/    rf_nfet_20v0_withptap_iso/\r\n",
      "cap_vpp_44p7x11p7_pol1m1m2m3m4m5_noshield/    rf_nfet_20v0_zvt_withptap/\r\n",
      "cap_vpp_44p7x23p1_pol1m1m2m3m4m5_noshield/    rf_nfet_g5v0d10v5/\r\n",
      "cap_vpp_55p8x11p7_pol1m1m2m3m4m5_noshield/    rf_npn_05v5/\r\n",
      "cap_vpp_55p8x23p1_pol1m1m2m3m4m5_noshield/    rf_pfet_01v8/\r\n",
      "diode_pd2nw_05v5/\t\t\t      rf_pfet_01v8_lvt/\r\n",
      "diode_pd2nw_05v5_hvt/\t\t\t      rf_pfet_01v8_mvt/\r\n",
      "diode_pd2nw_05v5_lvt/\t\t\t      rf_pfet_20v0_withptap/\r\n",
      "diode_pd2nw_11v0/\t\t\t      rf_test_coil1/\r\n",
      "diode_pw2nd_05v5/\t\t\t      rf_test_coil2/\r\n",
      "diode_pw2nd_05v5_lvt/\t\t\t      rf_test_coil3/\r\n",
      "diode_pw2nd_05v5_nvt/\t\t\t      special_nfet_latch/\r\n",
      "diode_pw2nd_11v0/\t\t\t      special_nfet_pass/\r\n",
      "esd_nfet_01v8/\t\t\t\t      special_nfet_pass_flash/\r\n",
      "esd_nfet_05v0_nvt/\t\t\t      special_nfet_pass_lvt/\r\n",
      "esd_nfet_g5v0d10v5/\t\t\t      special_pfet_pass/\r\n",
      "esd_pfet_g5v0d10v5/\r\n"
     ]
    }
   ],
   "source": [
    "!ls -F ~/tmp/skywater-pdk/libraries/sky130_fd_pr/latest/cells/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For my purposes, I only needed a simple NFET and PFET to build some logic gates. I figured 1.8V versions of these would be found in the `nfet_01v8` and `pfet_01v8` subdirectories, but I wasn't expecting all these files:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:04.287701Z",
     "start_time": "2021-04-30T19:52:04.147809Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sky130_fd_pr__nfet_01v8_aM02W1p65L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W1p65L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W1p65L0p18.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W1p65L0p18.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W1p65L0p25.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W1p65L0p25.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W3p00L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W3p00L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W3p00L0p18.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W3p00L0p18.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W3p00L0p25.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W3p00L0p25.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W5p00L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W5p00L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W5p00L0p18.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W5p00L0p18.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W5p00L0p25.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM02W5p00L0p25.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W1p65L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W1p65L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W1p65L0p18.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W1p65L0p18.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W1p65L0p25.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W1p65L0p25.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W3p00L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W3p00L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W3p00L0p18.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W3p00L0p18.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W3p00L0p25.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W3p00L0p25.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W5p00L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W5p00L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W5p00L0p18.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W5p00L0p18.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W5p00L0p25.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_aM04W5p00L0p25.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8.bins.csv*\r\n",
      "sky130_fd_pr__nfet_01v8__ff.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__ff.pm3.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__fs.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__fs.pm3.spice*\r\n",
      "sky130_fd_pr__nfet_01v8_hcM04W3p00L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_hcM04W3p00L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_hcM04W5p00L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_hcM04W5p00L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8__leak.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__leak.pm3.spice*\r\n",
      "sky130_fd_pr__nfet_01v8_mcM04W3p00L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_mcM04W3p00L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8_mcM04W5p00L0p15.cdl*\r\n",
      "sky130_fd_pr__nfet_01v8_mcM04W5p00L0p15.netlist.tsv*\r\n",
      "sky130_fd_pr__nfet_01v8__mismatch.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8.pm3.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__sf.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__sf.pm3.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__ss.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__ss.pm3.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__subvt_mismatch.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__tt.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__tt_correln.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__tt_correlp.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__tt_leak.corner.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__tt_leak.pm3.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__tt.pm3.spice*\r\n",
      "sky130_fd_pr__nfet_01v8__wafer.corner.spice*\r\n",
      "tests/\r\n"
     ]
    }
   ],
   "source": [
    "!ls -F ~/tmp/skywater-pdk/libraries/sky130_fd_pr/latest/cells/nfet_01v8"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "After some further poking about and reading, I categorized the files as follows:\n",
    "\n",
    "* Any file ending in `.cdl` seems to be associated with Cadence. Since I'll never have the money to run their software, I can ignore these and the associated `.tsv` files.\n",
    "* Files with names containing `_tt_`, `_ff_`, `_fs_`, `_sf_`, or `_ss_` refer to *[process corners](http://anysilicon.com/understanding-process-corner-corner-lots/)* where variations in the semiconductor fabrication process lead to NMOS/PMOS transistors that have typical, fast or slow switching characteristics.\n",
    "* Files ending with `.pm3.spice` contain most of the device parameters for a particular corner. These files are included inside an associated `corner.spice` file that makes a small adjustment to the parameters. Both these files are used for simulating transistors at a given process corner.\n",
    "* Files ending with `leak.pm3.spice` and `leak.corner.spice` are similar to the previous files, but are probably used for simulating transistor leakage currents.\n",
    "* Many of the `.spice` files contain multiple transistor models with differing parameters that are dependent on the length and width of the transistor gate. The file ending with `.bins.csv` contains a list of the supported transistor sizes. Some of the 1.8V NMOS and PMOS transistor dimensions are shown below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:04.350043Z",
     "start_time": "2021-04-30T19:52:04.290751Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>device</th>\n",
       "      <th>bin</th>\n",
       "      <th>W</th>\n",
       "      <th>L</th>\n",
       "      <th>device</th>\n",
       "      <th>bin</th>\n",
       "      <th>W</th>\n",
       "      <th>L</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>0</td>\n",
       "      <td>1.26</td>\n",
       "      <td>0.15</td>\n",
       "      <td>sky130_fd_pr__pfet_01v8</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.26</td>\n",
       "      <td>0.15</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>1</td>\n",
       "      <td>1.68</td>\n",
       "      <td>0.15</td>\n",
       "      <td>sky130_fd_pr__pfet_01v8</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.68</td>\n",
       "      <td>0.15</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>2</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.00</td>\n",
       "      <td>sky130_fd_pr__pfet_01v8</td>\n",
       "      <td>2.0</td>\n",
       "      <td>1.00</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>3</td>\n",
       "      <td>1.00</td>\n",
       "      <td>2.00</td>\n",
       "      <td>sky130_fd_pr__pfet_01v8</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.00</td>\n",
       "      <td>2.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>4</td>\n",
       "      <td>1.00</td>\n",
       "      <td>4.00</td>\n",
       "      <td>sky130_fd_pr__pfet_01v8</td>\n",
       "      <td>4.0</td>\n",
       "      <td>1.00</td>\n",
       "      <td>4.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>58</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>58</td>\n",
       "      <td>0.61</td>\n",
       "      <td>0.15</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>59</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>59</td>\n",
       "      <td>0.65</td>\n",
       "      <td>0.15</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>60</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>60</td>\n",
       "      <td>0.65</td>\n",
       "      <td>0.18</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>61</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>61</td>\n",
       "      <td>0.65</td>\n",
       "      <td>0.25</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>62</th>\n",
       "      <td>sky130_fd_pr__nfet_01v8</td>\n",
       "      <td>62</td>\n",
       "      <td>0.65</td>\n",
       "      <td>0.50</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>63 rows × 8 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                     device  bin     W     L                   device  bin  \\\n",
       "0   sky130_fd_pr__nfet_01v8    0  1.26  0.15  sky130_fd_pr__pfet_01v8  0.0   \n",
       "1   sky130_fd_pr__nfet_01v8    1  1.68  0.15  sky130_fd_pr__pfet_01v8  1.0   \n",
       "2   sky130_fd_pr__nfet_01v8    2  1.00  1.00  sky130_fd_pr__pfet_01v8  2.0   \n",
       "3   sky130_fd_pr__nfet_01v8    3  1.00  2.00  sky130_fd_pr__pfet_01v8  3.0   \n",
       "4   sky130_fd_pr__nfet_01v8    4  1.00  4.00  sky130_fd_pr__pfet_01v8  4.0   \n",
       "..                      ...  ...   ...   ...                      ...  ...   \n",
       "58  sky130_fd_pr__nfet_01v8   58  0.61  0.15                      NaN  NaN   \n",
       "59  sky130_fd_pr__nfet_01v8   59  0.65  0.15                      NaN  NaN   \n",
       "60  sky130_fd_pr__nfet_01v8   60  0.65  0.18                      NaN  NaN   \n",
       "61  sky130_fd_pr__nfet_01v8   61  0.65  0.25                      NaN  NaN   \n",
       "62  sky130_fd_pr__nfet_01v8   62  0.65  0.50                      NaN  NaN   \n",
       "\n",
       "       W     L  \n",
       "0   1.26  0.15  \n",
       "1   1.68  0.15  \n",
       "2   1.00  1.00  \n",
       "3   1.00  2.00  \n",
       "4   1.00  4.00  \n",
       "..   ...   ...  \n",
       "58   NaN   NaN  \n",
       "59   NaN   NaN  \n",
       "60   NaN   NaN  \n",
       "61   NaN   NaN  \n",
       "62   NaN   NaN  \n",
       "\n",
       "[63 rows x 8 columns]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "nfet_sizes = pd.read_table(\"~/tmp/skywater-pdk/libraries/sky130_fd_pr/latest/cells/nfet_01v8/sky130_fd_pr__nfet_01v8.bins.csv\", delimiter=\",\")\n",
    "pfet_sizes = pd.read_table(\"~/tmp/skywater-pdk/libraries/sky130_fd_pr/latest/cells/pfet_01v8/sky130_fd_pr__pfet_01v8.bins.csv\", delimiter=\",\")\n",
    "pd.concat((nfet_sizes, pfet_sizes), axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Knowing where the device files are and what they contain is great, but how do I actually *use* them? It turns out there is a master library file: `skywater-pdk/libraries/sky130_fd_pr/latest/models/sky130.lib.spice`. Internally, this file is divided into nine *sections* that cover the five process corners (`tt`, `ff`, `fs`, `sf`, `ss`) as well as four additional corners for the low/high variations in resistor and capacitor values (`hh`, `hl`, `lh`, `ll`). I'm only interested in using some typical FETs, so I can load that section into a SKiDL library like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:06.228285Z",
     "start_time": "2021-04-30T19:52:04.352429Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Bad element line, looking for word 1/2:\n",
      "include \"sky130_fd_pr__esd_nfet_05v0_nvt.pm3\"\n",
      "        ^\n",
      "Parse error on:\n",
      "include \"sky130_fd_pr__esd_nfet_05v0_nvt.pm3\"\n",
      "Problem parsing /home/devb/tmp/skywater-pdk/libraries/sky130_fd_pr/latest/models/r+c/../r+c.mrp1monte.spice - list assignment index out of range\n",
      "Empty Spice file: /home/devb/tmp/skywater-pdk/libraries/sky130_fd_pr/latest/models/head.spice\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sky130_fd_pr__cap_vpp_02p7x41p1_m1m2m3m4_shieldl1_fingercap: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm10w3p00l0p50: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm04w3p00l0p50: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm10w5p00l0p50: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm04w5p00l0p50: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm10w7p00l0p50: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm04w7p00l0p50: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm02w5p00l0p50: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm02w3p00l0p50: \n",
      "sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_noshield_o1nhv: \n",
      "sky130_fd_pr__res_xhigh_po_5p73: \n",
      "sky130_fd_pr__res_xhigh_po_0p69: \n",
      "sky130_fd_pr__nfet_g5v0d16v0__base: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm02: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm02w3p00: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm02w5p00: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm02w5p00l0p18: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm02w5p00l0p25: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm04: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm04w3p00: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm04w5p00: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm04w5p00l0p18: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_bm04w5p00l0p25: \n",
      "sky130_fd_pr__nfet_g5v0d10v5: \n",
      "sky130_fd_pr__res_high_po_2p85: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5_x: \n",
      "sky130_fd_pr__special_pfet_pass: \n",
      "sky130_fd_pr__cap_vpp_04p4x04p6_m1m2m3_shieldl1: \n",
      "sky130_fd_pr__pfet_g5v0d16v0__base: \n",
      "sky130_fd_pr__res_xhigh_po_2p85: \n",
      "sky130_fd_pr__esd_pfet_g5v0d10v5: \n",
      "sky130_fd_pr__res_xhigh_po_0p35: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldm5: \n",
      "sky130_fd_pr__esd_nfet_g5v0d10v5: \n",
      "sky130_fd_pr__cap_vpp_06p8x06p1_l1m1m2m3_shieldpom4: \n",
      "sky130_fd_pr__res_high_po_5p73: \n",
      "sky130_fd_pr__pfet_01v8_mvt: \n",
      "sky130_fd_pr__pnp_05v5_w0p68l0p68: \n",
      "sky130_fd_pr__model__parasitic__res_po: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3_shieldm4: \n",
      "sky130_fd_pr__esd_nfet_01v8: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_m1m4_noshield: \n",
      "sky130_fd_pr__cap_mim_m3_1: \n",
      "sky130_fd_pr__cap_vpp_02p9x06p1_m1m2m3m4_shieldl1_fingercap2: \n",
      "sky130_fd_pr__special_nfet_pass: \n",
      "sky130_fd_pr__cap_vpp_44p7x23p1_pol1m1m2m3m4m5_noshield: \n",
      "sky130_fd_pr__cap_vpp_11p3x11p3_m1m2m3m4_shieldl1_wafflecap: \n",
      "sky130_fd_pr__res_generic_pd: \n",
      "sky130_fd_pr__pfet_g5v0d16v0: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w3p00: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w5p00: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w3p00: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w5p00: \n",
      "sky130_fd_pr__cap_vpp_06p8x06p1_m1m2m3_shieldl1m4: \n",
      "sky130_fd_pr__res_xhigh_po: \n",
      "sky130_fd_pr__res_high_po: \n",
      "sky130_fd_pr__pfet_01v8_hvt: \n",
      "sky130_fd_pr__cap_vpp_04p4x04p6_m1m2m3_shieldl1m5_floatm4: \n",
      "sky130_fd_pr__cap_vpp_11p3x11p8_l1m1m2m3m4_shieldm5_nhv: \n",
      "sky130_fd_pr__pfet_g5v0d10v5: \n",
      "sky130_fd_pr__res_iso_pw: \n",
      "sky130_fd_pr__special_nfet_latch: \n",
      "sky130_fd_pr__nfet_03v3_nvt: \n",
      "sky130_fd_pr__res_high_po_0p69: \n",
      "sky130_fd_pr__cap_vpp_05p9x05p9_m1m2m3m4_shieldl1_wafflecap: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w3p00: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w5p00: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w3p00: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w5p00: \n",
      "sky130_fd_pr__nfet_01v8_lvt: \n",
      "sky130_fd_pr__res_xhigh_po_1p41: \n",
      "sky130_fd_pr__special_nfet_pass_flash: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm02: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm02w5p00: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm04: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm04w5p00: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm04w7p00: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm10: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm10w5p00: \n",
      "sky130_fd_pr__rf_nfet_g5v0d10v5_bm10w7p00: \n",
      "sky130_fd_pr__rf_pfet_01v8_mvt_af02w1p68l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_mvt_af02w0p84l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_mvt_af04w1p68l0p15: \n",
      "sky130_fd_pr__res_high_po_0p35: \n",
      "sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_noshield_o1phv: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3_shieldpom4: \n",
      "sky130_fd_pr__cap_vpp_08p6x07p8_m1m2m3_shieldl1: \n",
      "sky130_fd_pr__res_xhigh_po__base: \n",
      "sky130_fd_pr__cap_vpp_02p7x11p1_m1m2m3m4_shieldl1_fingercap: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w1p65l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w1p65l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w1p65l0p18: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w1p65l0p18: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w1p65l0p25: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w1p65l0p25: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w3p00l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w3p00l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w3p00l0p18: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w3p00l0p18: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w3p00l0p25: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w3p00l0p25: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w5p00l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w5p00l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w5p00l0p18: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w5p00l0p18: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm02w5p00l0p25: \n",
      "sky130_fd_pr__rf_nfet_01v8_bm04w5p00l0p25: \n",
      "sky130_fd_pr__cap_mim_m3_2: \n",
      "sky130_fd_pr__nfet_05v0_nvt: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3_shieldl1m5_floatm4: \n",
      "sky130_fd_pr__special_nfet_pass_lvt: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_l1m1m2m3m4_shieldpom5: \n",
      "sky130_fd_pr__cap_vpp_11p3x11p8_l1m1m2m3m4_shieldm5_nhv__base: \n",
      "sky130_fd_pr__cap_vpp_02p7x21p1_m1m2m3m4_shieldl1_fingercap: \n",
      "sky130_fd_pr__pfet_01v8_lvt: \n",
      "sky130_fd_pr__pfet_01v8: \n",
      "sky130_fd_pr__res_high_po_1p41: \n",
      "sky130_fd_pr__cap_var_lvt: \n",
      "sky130_fd_pr__res_generic_nd: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w1p65l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w1p65l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w1p65l0p18: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w1p65l0p18: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w1p65l0p25: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w1p65l0p25: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w3p00l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w3p00l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w3p00l0p18: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w3p00l0p18: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w3p00l0p25: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w3p00l0p25: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w5p00l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w5p00l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w5p00l0p18: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w5p00l0p18: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm02w5p00l0p25: \n",
      "sky130_fd_pr__rf_pfet_01v8_bm04w5p00l0p25: \n",
      "sky130_fd_pr__rf_pfet_01v8_af02w1p68l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_af02w5p00l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_af02w0p84l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_af04w1p68l0p15: \n",
      "sky130_fd_pr__rf_pfet_01v8_af02w3p00l0p15: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldm5: \n",
      "sky130_fd_pr__cap_vpp_02p7x06p1_m1m2m3m4_shieldl1_fingercap: \n",
      "sky130_fd_pr__cap_vpp_08p6x07p8_m1m2m3_shieldl1m5_floatm4: \n",
      "sky130_fd_pr__cap_vpp_08p6x07p8_l1m1m2_noshield_o1: \n",
      "sky130_fd_pr__nfet_g5v0d16v0: \n",
      "sky130_fd_pr__nfet_01v8: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_af02w0p84l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_af04w0p84l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_af04w3p00l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_af02w0p42l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_af02w3p00l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_af08w3p00l0p15: \n",
      "sky130_fd_pr__rf_nfet_01v8_lvt_af08w0p84l0p15: \n",
      "sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3_shieldl1: \n"
     ]
    }
   ],
   "source": [
    "# Select a particular corner using tt, ff, fs, sf, ss, hh, hl, lh, ll.\n",
    "corner = \"tt\"  # Use typical transistor models.\n",
    "\n",
    "# Create a SKiDL library for the Skywater devices at that process corner.\n",
    "sky_lib = SchLib(\n",
    "    \"/home/devb/tmp/skywater-pdk/libraries/sky130_fd_pr/latest/models/sky130.lib.spice\",\n",
    "    lib_section=corner,  # Load the transistor models for this corner.\n",
    "    recurse=True,  # The master lib includes sublibraries, so recurse thru them to load everything.\n",
    ")\n",
    "\n",
    "print(sky_lib)  # Print the list of devices in the library."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The progress messages indicate a few errors in the libraries (maybe they're corrected by now), but I'm not using those particular devices so I'm not going to worry about it. From the list above, I can pick out the 1.8V general-purpose transistors I want, but I also need to specify their gate dimensions so the right model gets loaded. I picked out a small NMOS FET, and then a PMOS FET that's 3x the width. (That's because I learned in my 1983 VLSI class that PMOS transistors have 3x the resistance-per-square of NMOS ones, so make them wider to make the current-driving capability about the same in each.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:06.253747Z",
     "start_time": "2021-04-30T19:52:06.230137Z"
    }
   },
   "outputs": [],
   "source": [
    "nfet_wl = Parameters(W=0.42, L=0.15)\n",
    "pfet_wl = Parameters(W=1.26, L=0.15)  # 3x the width of the NMOS FET."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now I can extract the NMOS and PMOS transistors from the library and use them to build logic gates:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:06.299396Z",
     "start_time": "2021-04-30T19:52:06.255746Z"
    }
   },
   "outputs": [],
   "source": [
    "nfet = Part(sky_lib, \"sky130_fd_pr__nfet_01v8\", params=nfet_wl)\n",
    "pfet = Part(sky_lib, \"sky130_fd_pr__pfet_01v8\", params=pfet_wl)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Some Infrastructure"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before I start building gates, there's some stuff that I'll use over and over to test the circuitry. The first of these is an *oscilloscope function* that takes a complete set of waveform data from a simulation and plots selected waveforms from it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:06.325022Z",
     "start_time": "2021-04-30T19:52:06.300608Z"
    }
   },
   "outputs": [],
   "source": [
    "disp_vmin, disp_vmax = -0.4@u_V, 2.4@u_V\n",
    "disp_imin, disp_imax = -10@u_mA, 10@u_mA\n",
    "\n",
    "def oscope(waveforms, *nets_or_parts):\n",
    "    \"\"\"\n",
    "    Plot selected waveforms as a stack of individual traces.\n",
    "    \n",
    "    Args:\n",
    "        waveforms: Complete set of waveform data from ngspice simulation.\n",
    "        nets_or_parts: SKiDL Net or Part objects that correspond to individual waveforms.\n",
    "        vmin, vmax: Minimum/maximum voltage limits for each waveform trace.\n",
    "        imin, imax: Minimum/maximum current limits for each waveform trace.\n",
    "    \"\"\"\n",
    "    # Determine if this is a time-series plot, or something else.\n",
    "    try:\n",
    "        x = waveforms.time  # Sample times are used for the data x coord.\n",
    "    except AttributeError:\n",
    "        # Use the first Net or Part data to supply the x coord.\n",
    "        nets_or_parts = list(nets_or_parts)\n",
    "        x_node = nets_or_parts.pop(0)\n",
    "        x = waveforms[node(x_node)]\n",
    "\n",
    "    # Create separate plot traces for each selected waveform.\n",
    "    num_traces = len(nets_or_parts)\n",
    "    trace_hgt = 1.0 / num_traces\n",
    "    fig, axes = plt.subplots(nrows=num_traces, sharex=True, squeeze=False,\n",
    "                               subplot_kw=None, gridspec_kw=None)\n",
    "    traces = axes[:,0]\n",
    "\n",
    "    # Set the X axis label on the bottom-most trace.\n",
    "    if isinstance(x.unit, SiUnits.Second):\n",
    "        xlabel = 'Time (S)'\n",
    "    elif isinstance(x.unit, SiUnits.Volt):\n",
    "        xlabel = x_node.name + ' (V)'\n",
    "    elif isinstance(x.unit, SiUnits.Ampere):\n",
    "        xlabel = x_node.ref + ' (A)'\n",
    "    traces[-1].set_xlabel(xlabel)\n",
    "\n",
    "    # Set the Y axis label position for each plot trace.\n",
    "    trace_ylbl_position = dict(rotation=0,\n",
    "                              horizontalalignment='right',\n",
    "                              verticalalignment='center',\n",
    "                              x=-0.01)\n",
    "    \n",
    "    # Plot each Net/Part waveform in its own trace.\n",
    "    for i, (net_or_part, trace) in enumerate(zip(nets_or_parts, traces), 1):\n",
    "        \n",
    "        y = waveforms[node(net_or_part)]  # Extract the waveform data\n",
    "        \n",
    "        # Set the Y axis label depending upon whether data is voltage or current.\n",
    "        if isinstance(y.unit, SiUnits.Volt):\n",
    "            trace.set_ylim(float(disp_vmin), float(disp_vmax))\n",
    "            trace.set_ylabel(net_or_part.name + ' (V)', trace_ylbl_position)\n",
    "        elif isinstance(y.unit, SiUnits.Ampere):\n",
    "            trace.set_ylim(float(disp_imin), float(disp_imax))\n",
    "            trace.set_ylabel(net_or_part.ref + ' (A)', trace_ylbl_position)\n",
    "        \n",
    "        # Set position of trace within stacked traces.\n",
    "        trace.set_position([0.1, (num_traces-i) * trace_hgt, 0.8, trace_hgt])\n",
    "        \n",
    "        # Place grid on X axis.\n",
    "        trace.grid(axis='x', color='orange', alpha=1.0)\n",
    "        \n",
    "        # Plot the waveform data.\n",
    "        trace.plot(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In addition to an oscilloscope, every electronics bench has a *signal generator*. For my purposes, I only need a simple function that generates one or more square waves whose frequencies decrease by a factor of two. (The collection of square waves looks like the output of a binary *counter*, hence the name.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:06.346144Z",
     "start_time": "2021-04-30T19:52:06.326612Z"
    }
   },
   "outputs": [],
   "source": [
    "default_freq = 500@u_MHz  # Specify a default frequency so it doesn't need to be set every time.\n",
    "\n",
    "def cntgen(*bits, freq=default_freq):\n",
    "    \"\"\"\n",
    "    Generate one or more square waves varying in frequency by a factor of two.\n",
    "    \n",
    "    Args:\n",
    "        bits: One or more Net objects, each of which will carry a square wave.\n",
    "    \"\"\"\n",
    "    bit_period = 1.0/freq\n",
    "    for bit in bits:\n",
    "        \n",
    "        # Create a square-wave pulse generator with the current period.\n",
    "        pulse = PULSEV(initial_value=vdd_voltage, pulsed_value=0.0@u_V,\n",
    "                       pulse_width=bit_period/2, period=bit_period)\n",
    "        \n",
    "        # Attach the pulse generator between ground and the net that carries the square wave. \n",
    "        gnd & pulse[\"n, p\"] & bit\n",
    "        \n",
    "        # Double the period (halve the frequency) for each successive bit.\n",
    "        bit_period = 2 * bit_period"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All the circuits in this notebook will run from a 1.8V supply, so the following function instantiates a global power supply and a $V_{dd}$ voltage rail for them to use:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:06.366673Z",
     "start_time": "2021-04-30T19:52:06.347916Z"
    }
   },
   "outputs": [],
   "source": [
    "default_voltage = 1.8@u_V  # Specify a default supply voltage.\n",
    "\n",
    "def pwr(voltage=default_voltage):\n",
    "    \"\"\"\n",
    "    Create a global power supply and voltage rail.\n",
    "    \"\"\"\n",
    "    # Clear any pre-existing circuitry. (Start with a clear slate.)\n",
    "    reset()\n",
    "    \n",
    "    # Global variables for the power supply and voltage rail.\n",
    "    global vdd_ps, vdd, vdd_voltage\n",
    "    \n",
    "    # Create a power supply and attach it between the Vdd rail and ground.\n",
    "    vdd_voltage = voltage\n",
    "    vdd_ps = V(ref=\"VDD_SUPPLY\", dc_value=vdd_voltage)\n",
    "    vdd = Net(\"Vdd\")\n",
    "    vdd & vdd_ps[\"p, n\"] & gnd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, here are some convenience functions that 1) generate a netlist from the SKiDL code and use that to create a PySpice simulator object, 2) use the simulator object to perform a DC-level analysis, 3) use the simulator to perform a transient analysis, and 4) count the number of transistors in a circuit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:06.389863Z",
     "start_time": "2021-04-30T19:52:06.368002Z"
    }
   },
   "outputs": [],
   "source": [
    "get_sim  = lambda         : generate_netlist().simulator()  # Compile netlist & create simulator.\n",
    "do_dc    = lambda **kwargs: get_sim().dc(**kwargs)          # Run a DC-level analysis.\n",
    "do_trans = lambda **kwargs: get_sim().transient(**kwargs)   # Run a transient analysis.\n",
    "\n",
    "def how_big(circuit=default_circuit):\n",
    "    from collections import defaultdict\n",
    "    parts = defaultdict(lambda: 0)\n",
    "    for p in circuit.parts:\n",
    "        parts[p.name] += 1\n",
    "    for part_name, num_parts in parts.items():\n",
    "        print(f\"{part_name}: {num_parts}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the infrastructure in place, I can begin building logic gates, starting from the simplest one I know."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Simplest: the Inverter\n",
    "\n",
    "Here's the gate-level schematic for a CMOS inverter:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![CMOS inverter transistor schematic](https://allthingsvlsi.files.wordpress.com/2013/04/cmos-inverter.png?w=286&h=300)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And this is it's SKiDL version:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:06.416444Z",
     "start_time": "2021-04-30T19:52:06.394530Z"
    }
   },
   "outputs": [],
   "source": [
    "@package\n",
    "def inverter(a=Net(), out=Net()):\n",
    "    # Create the NFET and PFET transistors.\n",
    "    qp, qn = pfet(), nfet()\n",
    "\n",
    "    # Attach the NFET substrate to ground and the PFET substrate to Vdd.\n",
    "    gnd & qn.b\n",
    "    vdd & qp.b\n",
    "    \n",
    "    # Connect Vdd through the PFET source-to-drain on to the output node.\n",
    "    # From the output node, connect through the NFET drain-to-source to ground.\n",
    "    vdd & qp[\"s,d\"] & out & qn[\"d,s\"] & gnd\n",
    "    \n",
    "    # Attach the input to the NFET and PFET gate terminals.\n",
    "    a & qn.g & qp.g"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, I'll test the inverter's transfer function by attaching a voltage ramp to its input and see when the output transitions. (For those playing at home, you may notice the SPICE simulations take a minute or two to run. These transistor models are *complicated*.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:37.600560Z",
     "start_time": "2021-04-30T19:52:06.418376Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()  # Apply power to the circuitry.\n",
    "\n",
    "inv = inverter()  # Create an inverter.\n",
    "\n",
    "# Attach a voltage source between ground and the inverter's input.\n",
    "# Then attach the output to a net.\n",
    "gnd & V(ref=\"VIN\", dc_value=0.0@u_V)[\"n, p\"] & Net(\"VIN\") & inv[\"a, out\"] & Net(\"VOUT\")\n",
    "\n",
    "# Do a DC-level simulation while ramping the voltage source from 0 to Vdd.\n",
    "vio = do_dc(VIN=slice(0, vdd_voltage, 0.01))\n",
    "\n",
    "# Plot the inverter's output against its input.\n",
    "oscope(vio, inv.a, inv.out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For a low-level input, the inverter's output is high and vice-versa as expected. From the shape of the transfer curve, I'd estimate the inverter's trigger point is around 0.8V."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's also interesting to look at the current draw of the inverter as the input voltage ramps up:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:52:37.914449Z",
     "start_time": "2021-04-30T19:52:37.601720Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Add a trace for the Vdd power supply current.\n",
    "disp_imin, disp_imax = -15@u_uA, 1@u_uA\n",
    "oscope(vio, inv.a, inv.out, vdd_ps)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As we learned in our textbooks so long ago, the quiescent current for CMOS logic is near zero but surges as the input voltage goes through the transition zone when both transistors are ON. For this inverter, the current maxes-out at about 13 $\\mu$A at the trigger point."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's equally easy to do a transient analysis of the inverter as it receives an input that varies over time:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:53:10.325456Z",
     "start_time": "2021-04-30T19:52:37.915855Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "# Connect a 500 MHz square wave to net A.\n",
    "a = Net(\"A\")\n",
    "cntgen(a)\n",
    "\n",
    "# Pump the square wave through an inverter.\n",
    "inv = inverter()\n",
    "a & inv[\"a, out\"] & Net(\"A_BAR\")\n",
    "\n",
    "# Do a transient analysis and look at the timing between input and output.\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=3.5@u_ns)\n",
    "oscope(waveforms, a, inv.out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There is a bit of ringing on the inverter's output but no appreciable propagation delay, probably because there is no real load on the output. In order to get more delay, I'll cascade thirty inverters together and look at the output of the last one:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:53:43.783669Z",
     "start_time": "2021-04-30T19:53:10.326803Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "a = Net(\"A\")\n",
    "cntgen(a)\n",
    "\n",
    "# Create a list of 30 inverters.\n",
    "invs = [inverter() for _ in range(30)]\n",
    "\n",
    "# Attach the square wave to the first inverter in the list.\n",
    "a & invs[0].a\n",
    "\n",
    "# Go through the list, attaching the input of each inverter to the output of the previous one.\n",
    "for i in range(1, len(invs)):\n",
    "    invs[i-1].out & invs[i].a\n",
    "    \n",
    "# Attach the output of the last inverter to the output net.\n",
    "invs[-1].out & Net(\"A_DELAY\")\n",
    "\n",
    "# Do a transient analysis.\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=3.5@u_ns)\n",
    "oscope(waveforms, a, invs[-1].out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Thirty cascaded inverters creates a total delay of around 0.65 ns, so each inverter contributes about 20 ps. This simulation doesn't include things like wiring delays, so don't get your hopes up about running at 50 GHz."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, just to test the `how_big` function, let's see how many transistors are in 30 inverters:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:53:43.803628Z",
     "start_time": "2021-04-30T19:53:43.784906Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V: 1\n",
      "PULSEV: 1\n",
      "sky130_fd_pr__pfet_01v8: 30\n",
      "sky130_fd_pr__nfet_01v8: 30\n"
     ]
    }
   ],
   "source": [
    "how_big()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Thirty NMOS and thirty PMOS transistors. We're good to go."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Universal: the NAND Gate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "They say if you have a NAND gate, you have it all (if all you want is combinational logic, which seems a bit limited). Here's the schematic for one:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![CMOS NAND gate schematic](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.allaboutcircuits.com%2Fuploads%2Farticles%2FCMOS-NAND-gate-schematic-diagram.jpg&f=1&nofb=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And this is its SKiDL version:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:53:43.826447Z",
     "start_time": "2021-04-30T19:53:43.805363Z"
    }
   },
   "outputs": [],
   "source": [
    "@package\n",
    "def nand(a=Net(), b=Net(), out=Net()):\n",
    "    # Create the PFET and NFET transistors.\n",
    "    q1, q2 = pfet(2)\n",
    "    q3, q4 = nfet(2)\n",
    "    \n",
    "    # Connect the PFET/NFET substrates to Vdd/gnd, respectively.\n",
    "    vdd & q1.b & q2.b\n",
    "    gnd & q3.b & q4.b\n",
    "    \n",
    "    # Go from Vdd through a parallel-pair of PFETs to the output and then\n",
    "    # through a series-pair of NFETs to ground.\n",
    "    vdd & (q1[\"s,d\"] | q2[\"s,d\"]) & out & q3[\"d,s\"] & q4[\"d,s\"] & gnd\n",
    "    \n",
    "    # Connect the pair of inputs to the gates of the transistors.\n",
    "    a & q1.g & q3.g\n",
    "    b & q2.g & q4.g"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Like with the inverter, I'll do a transient analysis but using two square waves to drive both NAND inputs:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:54:16.001686Z",
     "start_time": "2021-04-30T19:53:43.827726Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAFNCAYAAABG7LsFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAxC0lEQVR4nO2dfZxdVXnvv8+ZySSEBIQkIBDigPJihAIyikoVQauIL+it2qDVeqWl7dX7EbUv9LZevfZatbd6aa29vViR6lWgCkV6eVMogrSITEJ4jZCIQIIxCcZAEJLMzHn6x97nzGGYyczsOXs/k71+389nPnPO2XvOetbsvddvPWs961nm7gghhBBV04g2QAghRJpIgIQQQoQgARJCCBGCBEgIIUQIEiAhhBAhSICEEEKE0BttQCSLFy/2/v7+4l+wfS0sPKJr9uxRqO7RVsSgukdbUT0zrPfKlSsfc/cl4x1LWoD6+/sZHBws/gXXDsDpM/j7PRnVPdqKGFT3aCuqZ4b1NrOHJzqmITghhBAhSICEEEKEIAESQggRggRICCFECBIgIYQQIUiAhBBChCABEkIIEYIESAghRAi1EiAzO9TMbjSz+8zsXjP7ULRNQgghxqdumRCGgY+6+yozWwisNLPvuvt90YYJIYR4JrXygNx9o7uvyl9vB9YAh8RaJYQQYjxqJUCdmFk/cAJwW7ApQgghxqGWAmRmC4DLgHPd/Ykxx84xs0EzG9yyZUuMgUIIIeonQGY2h0x8vu7ul4897u4XuPuAuw8sWTJuhnAhhBAVUCsBMjMDvgyscffPR9sjhBBiYmolQMDJwHuA08xsdf5zRrRRQgghnk2twrDd/RbAou0QQggxObUSoCpZ+fBWNmw6hjODyn/8qSGuX7OJEfeQ8geeWsThISXDo9ue5t/WPRZStgGn7FzAASGlwwObtrN6/baQsuf0GK8b7mPvkNLhhz/ZykM//2VI2Xv39XK6Gz0hpcO//mgTjz25K6bwjcfzlqER5s3pfu0lQAW5fNWjXLfuDWEC9I0fPsJnr/1RUOnwqv3ewFeDyv7cdfdz+R2PBpUOZy89mY8FlX3eZXex6pFtQaXDZ448hhVBZb/3wtvYMdQMKh0uO2EpJwaUu+mJHbz/ositwN/GqTuGJUCzCTNoBo727RweAeD7f3QqVrEZH/zGHex4Yk61hXawc7jJ8xbN5+u/fVLlZb/pC7ewoxlX9x1DTU5+wSI+++u/Umm5254aCq/7zuEm73tFP7/9ysMqLXf1+m3ZPd+MaS53DGXP+p+98YWcfsxzqzfgpjez/97lTKVLgArSMCNo9AuAZl72ofvPr7zsveb0MFJ5qaM03enrabB0v+rr3ttohF53B+b39VZe9wVzd7XLj8Id9tlrTuV13/j4jrz8mA5n635btKAv5J5n3uPQKKfudYuCqwwj1gNy98o9nxZm0Ax6GCEToEZQ5c3Ao697QLmWlxp13T1vhUtqB3dLq8io572Z191qGF8lASqImQU3RHHhfo3ZUPeg4hvhAkSI+FreUkTVveXxRzTClv+/o7y/VrlR93yZSIAKYhbnkkO8FxDp/TV9tFGoGsPCvb+IqreKjBKgUA8oLzPa+4u658tEAlSQzAuIw4npCUP2IEQ2wpE+SCNcfGM6Hq0yo6572wMKKL7R9oBi6x4hvmUjASpIYxbMg0S1g9EPQtOhEXTnWnDwiRPdCMfQDPQCWvd7dBBCVIezTCRABYmeA8LjhMCIFV9POgghphGOHoYaa0elZbYCMMKDEOqHBKgg8fMgHhYVEx2E0Ew6AMND50HihqFac0Dpia+3hx/rJ0ESoIIYwUMxkR6QWWwIOnEPY/zQa0wjHD0P0m6EA8qePcOPQQaUiASoINHhuKGRYMGNcOwaqFjxbYatA2qVn64HFC2+mgMSbcIbYeIa4egghKi1MNAKvw8pGoibA4r2AiLXwrTrHjUER1wIetlIgAoSPxcQNw8yK9bCBJVtRAchBK0Dip4HabbsCJwDil6EKwESLQxoBv77mu40grpEjUZ0IxznAYV3PIhajBk8B0RcJFgjWny1EFWMpf1ABo3HhHpAs2AeJG4NVLz3Fye+aS7GjE7F0wwMwCgbCVBB2hOTQXdlaCoeYtMQRXkBMBvC7+OGYiIzYER6Aa0S49MQ1U+CJEAFmQ2TsnGhyMFpiALXQIVnQgiMfoxMQxTpAUWnIWrdbhIg0WZ0XDhqCC42Ci42DDsuFU90+H3UQlSIFd/WHFDETR+9BqrZ1DogMYbROaCY8qMXosaugYr0gIIFiLh9YSIjAD10Dij7He0BSYBEGwv2gKIb4fhMCDFlz44ghJiyIyMARzMhRC5EjUEb0olnEX0zhHpAWPBeSJH7AQUHITQ9yQwYo5kQqi97NAouprmM9P7KRgJUkOg5oMhGOJsHCSTReRCYBd5f2DqgURuqJn4dUG5HDRVIAlSQ6DDs2FQ80cNQkdmwo4MQ0kxD1AxcDBMd8artGApiZm81Mzezo3dzzl5mdpOZ9ZjZg2Z21Jjj55vZH5vZsWZ20STlXWhmm83sni5VYUJGQzMDF6IGroWJDkKI3A02OgoubAEysdcdgpKR5r/jgxDqJ0Fle0BnAbfkvyfi/cDl7j4CXAKsaB0wswbwduASd78bWGpmy3bzXRcBp8/U6OnQDIuCi22EQ4MQAsU3OgQ92w02aOi1ESe+kV5AdBoibcdQADNbAPwqcDYdojIO7wa+nb++GPiNjmOvAh5294fz9/+yu+9y95uBrUVtng6N4NCY8GGo6GSkiYpvM3T9V2QmhNyGgEmD9pbcyoTQdcq8nGcC17r7A8DPzezEsSeYWR9wuLs/BJB7OU0zOy4/ZQWZKLUYBF5Zos1TJj4IIXpb6lgityMPD0IIXAcUvy11RBh2cCYERcEV4iyyITXy3+MNwy0Gto357GJghZn1Am8FvtlxbDNw8EyMMrNzzGzQzAa3bNkyk+8BgvdHSbAnDGlvR55uJoSWDdWX3Ygd7OhIRlo/Beot40vNbH/gNOBYM3OgB3Az+0N/Zvrop4F5Y/78EuA7wE3AXe6+qePYvPxvCuPuFwAXAAwMDBS+p6I9oNA5IIIXogam4oneiDA2GWn8MFRMMtJYD0hzQNPn7cDX3P157t7v7ocCP2HM8Jm7/wLoMbN5HZ/9GHgM+AzPHH4DOBIoPcJtSigVT0zhyAOK3I4hxWEoy1vJ6CwQmgOaOmcB/zzms8sYfxjuO2TBCp1cDBwNXD7m81OBqyYq1MwuBm4FjjKzDWZ29nSMng5ttzzBVDwNi82EELkYMzoNUewC5MgouOx3xD0fnYzUa+wBlTIE5+6njvPZ30xw+heBDwPXd5x7PnB+50lmNhcYAM7dTbm7C/fuKq0HIWwOKHwoJo7ILQlC50GCFyRGDr22smGHeED57+h1QPKASsDdVwE3mlnPJKcuA85z9+EKzJqU6Dmg6FQ8sdsxRCbkTHcoJlJ8m82WDdWXPWsyIdRPf8rxgKaLu184hXPWAmsrMGdKRKfigdisyOHDUEFlR0YARibkhCzwI0x8CQxCaHc2Y4cfFYYt2oyuDYj0gEKKhkAvALLGKHQ78uCEnGFDr8QvRI3JhJDbED4HVD8FkgAVpO2WJ5iKJzoIodkkzAWKzITQDG6IUh1+jA9CyH7XT34kQIVp3QxhY+KBw1CZFxBLihmh2w1R0uJbfdnxQQhKxSPG0FoIGbojaqAHFJ8JIYZUvQCIXYQbux9QPtweJb6BARhlIwEqSHQYNgRnhI7OhJCg+IYHIQS2gM3AcajogKPR614/BZIAFWQ0Mia9ZKSYhW1PDLEZoUPT0bRsiExGGp4JISIKLngOqG1HSPGlIgEqSPumTDAVT3QWiCwTQtxamBTnQSA2E0L0ItzYoVdFwYkxRDfC0al4IDYCMLQRDg5CCJ0DCvYCUhx61XYM4llEzwGFpuLJf0eugQrdDyi8JxxSfOb9Rc1/NaPrHrkXUm5DDQOxJUAFiU7FE7otdaO1CDemfA/1/mbDivi4ukcRPQ8SmoYoOPikTCRABQmfAwrMBtBpQwShHtBsmAeJ9AKi98QJDMCID0KonwJJgAoSHwUXOxkN0XNA6c2DtIdiIudBooaBgudBYueA6puMVAJUkNnQCEcPxUROxicZhBC4JQHEen/x4pvuAuQykQAVZDak4oki2vtzAiPBiG+IklwHNAvENzz8PqT0cpEAFSQ6FU9kI9xOTRIagh5D2pkQYsqFTg8opvzIHIDRwSdlIgEqSHwYdtxamLYNUeX6aCRe1YRmQghvhGfDPEiKnm9e9xq21jWsUjVED0NFpuJpz381Q4oP9YBmxVBM5E640eIbUnrW4YleiFo//0cCVJjwMOzQXUFzG4J8oMhUPI3AoZjoyejQEPTgLQlC0xBpOwYxlvhUPLH50Fo2RBA5/DgrhuBCSo8NQojeksCYDeH3IcWXigSoILNhDih6MjoyC0SK60HaQQhBT22sFzBqQwShaYi0HYMYS7sRDnIDQnPBBQ8/RidiTbURbjTi98SJIjQNkTwgMZbRPUJiiEzFY8HDj1kIekjRQORQTGwjbMQFYMTPf0XuhRSbhqhMJEAFiY+Ci0/FEzcHRFjls0wIsQ1RZCMcHoocmQEjeA5IyUj3AMzsdDO738zWmdl5ZZXTbgRSzIfWsiGg8qONcOVFA61GOIbooZjQdUD578gMGKl6f2VSKwEysx7gi8AbgOXAWWa2vJyyst+RXkBkNgCIqXv03iipb8cQ5wVEZwKPD0Koof7US4CAlwLr3P1Bd98FXAKcWUZBs2EtTIpzQNEe0OxYDxJS/CzZDTam/KjIQ6j3dgy90QZ0mUOA9R3vNwAnlVNUdjN84YZ1XPLD9ZOc2302PbGDX1m6b+XlwuiD8LEr7mF+X7W3UHhv0GBns5cPfH1V5UU/sWNo1IgADHjo6f1D6v7otqc7rKgew7htW39I3e/ftL2W3g/UT4AmxczOAc4BWLZsWeHvOWzx3pywz3q2PrWArU/t6pZ5U+bg5+zFr75gceXlAhx7yL4sX7CR9b9YEFL+UQcu5MXP2y+k7Jcdtogbb7+V+zftE1L+sYfsy9HPXRhS9ilHLeHhR+7h/k3bQ8p/af/+HPyceSFlv275gXxv1UNhdT/jmINCyi0biwqlLQMzeznwCXd/ff7+TwDc/dPjnT8wMOCDg4PFC7x2AE6fwd/vyaju0VbEoLpHW1E9M6y3ma1094HxjtVtDuh24AgzO8zM+oAVwJXBNgkhhBiHWg3BufuwmX0QuA7oAS5093uDzRJCCDEOtRIgAHe/Grg62g4hhBC7p25DcEIIIfYQJEBCCCFCkAAJIYQIQQIkhBAiBAmQEEKIECRAQgghQpAACSGECEECJIQQIgQJkBBCiBBqlYx0uixevNj7+/uLf8H2tbDwiK7Zs0ehukdbEYPqHm1F9cyw3itXrnR3H9fZqV0qnunQ39+PsmEXRHWPtiIG1T3aiuqZeTbsCTdR0hCcEEKIECRAQgghQpAACSGECEECJIQQIgQJkBBCiBAkQEIIIUKQAAkhhAhBAiSEECKEWgmQmR1qZjea2X1mdq+ZfSjaJiGEEONTt0wIw8BH3X2VmS0EVprZd939vmjDhBBCPJNaeUDuvtHdV+WvtwNrgENirRJCCDEetRKgTsysHzgBuC3YFCGEEONQSwEyswXAZcC57v7EmGPnmNmgmQ1u2bIlxkAhhBD1EyAzm0MmPl9398vHHnf3C9x9wN0HlixZUr2BQgghgJoJkJkZ8GVgjbt/PtoeIYQQE1MrAQJOBt4DnGZmq/OfM6KNEkII8WxqFYbt7rcAFm2HEEKIyamVAFXJyoe3smHTMZwZbUgQ3996OBsH10ebUTkGnLJzAQdEGxLAU7uG+c6mY9mV4HXfu6+X093oiTakZkiACnL5qke5bt0bkhSgJ3cO89673oPfdVe0KSGcvfRkPhZtRABX3/0z/mDN22FNmtf9shOWcmK0ETVDAlQQM2gmOto3NNzEaXDua4/g7ScujTanUt70hVvY0ZwTbUYIO4dHAPj2B05m0YK+YGuqY/X6bXzwG3ewo6nmstvoP1qQhhnu0VbE0Mwrvt/8PpbuNz/YmmrpbTQSvu7Z74OeM48DFs6LNaZCNj6+AwD3NDucZVK3KLjKMNL1gFoNUSPB6puBJ3rdPVfehqVV/1ZtU33ey0QCVBAzS7chImuILLGGCDLRTfa6tzseadW/dZ8n6viWigSoIGbpuuSthiixdggAw2gmet1bQ6+p1b51n6d63ctEAlSQhlmyPaJUe8KQeUCpDsWket0bbQ8orXpXgQSoIA1Lt0eUak8Y8qHXRHsezbbrG2tH1bTmOlMd8SgTCVBB0p4DykitJwxpByG0SC34xPLrnarnWyYSoIKkvA6o2UyzJwytodcEK06H55tYx0NzQOUhASqIke5QTKpzAZD20KsnGn7fUBRcaUiACpJ0OC5pzwEl6/m2Hd+06t/qZ6X6vJeJBKgglnBPuL0QNcG7Jwu/j7YihtH1X8GGVEzbA0r0eS+TBJuQ7pDyXECqK+Ih8/rSve7Z79Sue3sOKNHrXiYSoIJkqXjS/Pc1E/UAIO2ORyv4JDH9ac95pTriUSZptqBdoJ2eI8nxmHQ9oIalmwkh1fB7peIpDwlQQdoTkwnelc2UU/GkHH6f6ALkVn1T9XzLRAJUkJRDM1OdC4C0MyGkmgOwdZ+n6vmWiQSoIKPjwum1Rqn2hCHx8PtEF6IqF1x5SIAKMjoHFGxIAKmuiIe0U/E40KAZbUblKBNCeUiACmIJe0CpDsVA2kEITXdSzAE/uhBVdBsJUEFSWw3eSdJzQKQbhOAODUuvGR6NglNz2W30Hy1IynNA3g7DDjYkgJSDEJpOkh6Q1gGVhwSoIArDTnUILuU5IE/0mqcb8Vo2pQmQmY2Y2Wozu9PMVpnZKyY4by8zu8nMeszsQTM7aszx883sj83sWDO7aJIyLzSzzWZ2TxerMi6joZnp3ZapRkNB4vtAOTQSbIZbV1seUPcp0wN62t2Pd/fjgD8BPj3Bee8HLnf3EeASYEXrgJk1gLcDl7j73cBSM1u2mzIvAk7vhvFTJcW0NAlvB5T4dgypBiEoDLssqhqC2wf4xQTH3g18O399MfAbHcdeBTzs7g/n7/+FDoEai7vfDGydmalTo5F0aEy6qXhS344hxSCE9pbciV73MilTgPbKh+B+BPwD8OdjTzCzPuBwd38IIPdymmZ2XH7KCjJRajEIvLJEm6dMykEIKc8BGWnO+0ErDDs9TJkQSqOKIbijyYbFvmrPnjRYDGwb89nFwAoz6wXeCnyz49hm4OCZGGVm55jZoJkNbtmyZSbfA6TpALWyIqfoAaWcDdsdLGkPSHSbSobg3P1WMrFZMubQ08C8MZ9dArwTeC1wl7tv6jg2L/+bmdhygbsPuPvAkiVjzZk6KXtArRqn2AynvBFhsnNAyAMqi0oEyMyOBnqAn3d+7u6/AHrMbF7HZz8GHgM+wzOH3wCOBEqPcJsSSsWTZBRc0h4QiUbB5a1kqte9TKqYA1oNXAr8Vh7pNpbvAL865rOLgaOBy8d8fipw1UQFmtnFwK3AUWa2wczOLmr8ZLTd8hQVqJ0JIdaMCFLfjiHNIARFwZVFb1lf7O49Uzz1i8CHges7/vZ84PzOk8xsLjAAnLubMs+appmFabnl6T2OnUEI6T2QKWdCcE902DX/rSG47hOeCcHdVwE3mtlkgrUMOM/dhyswa1LSngNKNxVPypkQmskGIaTb2Syb0jyg6eDuF07hnLXA2grMmRJKxZNmGHbK2bAz6U3vhtd2DOUR7gHtqZhS8aQ5BEfCHlAz0SAELUQtDQlQQRoJR8G19wOKNSOElDMhKBlpgpUvGQlQQVq3YooC1PL6UlyIapbmNYc8FU+KHlD+W0Nw3UcCVJBG/p9Lcwgu+52iAKUdhOBJByGk6vmWiQSoIGmHYbfmgIINCSDpIIREN6RLOeCobCRABRmNjEnvrmyn4kmwHbbEPaAkh+A0B1QaEqCCWNJBCLkHlOADmXYQQpqdDkh76LVMJEAFSTkVT3sOKMG7p5FwJoRUgxAg8aHXEkmwCekOac8BZb+T9IBItyecdbZSvOPTzgFYJhKggigVT7qpeFLtCXuiO6JC2jkAy0QCVJCU54BSTsVjSW/HkGrN0/Z8y0QCVJCko+BSTsWT8FBMs5muB6Q5oHKQABVEqXhSXYia7lCMJ5qMFBQFVxYSoIIoFU+iueBItyFqJroQFdIOvy8TCVBBlIonXQ8o1aGYtIMQ0uxslo0EqCBph2Gnm4on5UwI7qnWPG3Pt0wkQAVJOggh/52mAKU7FNN0T9YDajTS9XzLRAJUkJTDsFOOgmskPBTjpDsH1Eg4/L5MJEAFSTkVT7M9BxRrRwQpD8ElHYRAuuH3ZSIBKkjKc0CjO6Km90CmHYSQ5o6okA+9Jnrdy0QCVJB2Kp5mehI0uiNqsCEBpDwU40knI422oJ5IgAoyukdIeowGIaT5VKY6FOOkG4RgCecALBMJUEGSjoJLOAw7y4SQYMXJUvGkOgeUsudbJrUTIDM73czuN7N1ZnZeWeW0F2Em+DymvBA1C0JIk5RT8SgIoRxqJUBm1gN8EXgDsBw4y8yWl1NW9jvBKaCkU/GkvB1D09P0ekFBCGVRKwECXgqsc/cH3X0XcAlwZhkFtcOwE+wRpuwBJT0Uk3IQQt1ayllCb7QBXeYQYH3H+w3ASeUUlTVCX7hhHZf8cP0k59aLBx/7ZfYixXbYYGezlw98fVW0JZWzdvN2lvelKUCGcdu2/iSvOz97B39xyhD77jWn619dNwGaFDM7BzgHYNmyZYW/57DFe3PCPuvZ+tQCtj61q1vm7TGcsv9aFsw9I9qMynnZYYu48fZbuX/TPtGmVM6iBXN59cJ10WaE8LrlB/K9VQ9x/6bt0aZUzy8PYKSkuQar00p+M3s58Al3f33+/k8A3P3T450/MDDgg4ODxQu8dgBOn8Hf78mo7tFWxKC6R1tRPTOst5mtdPeB8Y7VbWTzduAIMzvMzPqAFcCVwTYJIYQYh1oNwbn7sJl9ELgO6AEudPd7g80SQggxDrUSIAB3vxq4OtoOIYQQu6duQ3BCCCH2ECRAQgghQpAACSGECEECJIQQIgQJkBBCiBAkQEIIIUKQAAkhhAhBAiSEECIECZAQQogQapWMdLosXrzY+/v7i3/B9rWw8Iiu2bNHobpHWxGD6h5tRfXMsN4rV650dx/X2aldKp7p0N/fj7JhF0R1j7YiBtU92orqmXk27Ak3UdIQnBBCiBAkQGKP44o7HuVrP3g42gxRIe7OJ668l3sefTzaFNFFJEBij+PcS1fzsSvuiTZDVMhjT+7ion9/iPd95fZoU0QXkQAJIWY9O4ZGAJjbqyarTuhqCiFmPW0BmqMmq07oagohZj07h5sAzO3tCbZEdBMJkBBi1tPM1ys2LNgQ0VUkQEKIWc9wsyVAUqA6USsBMrNDzexGM7vPzO41sw9F2ySEmDnNXICkP/WiVgIEDAMfdfflwMuAD5jZ8mCbhOgaT+4cZnikGW1G5Yy0BCjYjigef2oo2oRSqJUAuftGd1+Vv94OrAEOibWqHM6//gE+cunqaDNExRzz8ev46DfvjDajckZaOSsTdIGuvnsjx33yO9y5flu0KV2nVgLUiZn1AycAtwWbUgrnX7+Wy+94NNoMUSE7h7NQ5G+v/mmwJdXTzJ2+9OQHbvzRZgDWbHwi2JLuU0sBMrMFwGXAue7+xJhj55jZoJkNbtmyJcbAPZyfbnuaM1f+Dus2b482JSme3DEcWv7lqzZw9t3vIiKD/nAzvWHHFkP5kOucnvo117WrkZnNIROfr7v75WOPu/sF7j7g7gNLliyp3sAacMvax7hz+1K+dPNPok1JiqGR2K1TPvJPd3LDz49i+87qhTDlMOxW5F8dN86plQCZmQFfBta4++ej7akrjbwVGEq4VxrBbPECWlkJqqQVd2EJzgH19mR1rmPwSa0ECDgZeA9wmpmtzn/OiDaqTFrRQVUyJ38gonvkqTE8S/7fO4eqbwhTjoLraWTN9HDAs142tdqQzt1vIbF7dNdwk736qk1P0ps/ECMBPfKUd/CNboB6GsZI09vBEFXSGoJL0AGiNx9xiOhslk2tBKhq7t3+XFbd+hAL5815xuc+ZrR2bJv5rPeMPe67Pd7JNfdspKdhuGflNpvZ+WU21FfdvRGA6+/bzDcH11c6Nj0bBGjl44fyyB0bMIymO02fml0TnTG2TZ3ovE2P72i/vvaen7FjaATHn3E/tV53fkfLtpn+51oN4Ff+7SGOP/Q5lV73VgiyBfUvR5rONZtfxPAdj07rOdvd0ale9wc2ZcE+31/7GIsXzGXXSNYBaF/rzuvf+t3x4Yyv08bjecvQCPPmdL+ja7PhgY5iYGDAZ7Il9xn/8x+478mDumiRmA4PfeaNlZe59Ze7ePmnrmZnc87kJ4uu82vLD+RL7x2ovNxvrdzAHyS4/qrF7X/6WpYsnFvob81spbuPe9HkAc2Arbvm86KD9+ELZ53wrMnRsb2bsUMH4/XkJhte6Dy+a7jJv/5oM8cd+hz2m99Hw7JoGbPsu8scqnjlX94IwNfOfin9i/Z+lm1l86mr1nDL2seqK7CDBzZtZ2dzDp8880W88ogl7f/7VBl76kT9v4nO++m2p7lv4xO8pH9/5vf1tMvuPL91b41nVtHrtHO4yWs+dxMAN//hqdl9VrEz8trP38T+8/uqLTTn7g3bALjho6fQkz9nU73u45023es++PBWehsNjjxwIX29jXbr0Tq/sz3p5nUH4KY3s//e5UylS4BmwOZdC/n1o5Zw+JIFIeVHlduif9HeHLr//MrLPfg5e4WFpD6dR4Adc8i+HLZ478rLP3T/+Zx0+KLKy+0cKVm2qPprDrD//L72XFDV7BhqcmDfEzw/6JmLeM7azHu8tPj3ukXBVcZI02nSoK8n3f1JWuGhVdMwwhqinbkAzUtsX5rZEP5sZkTNwz89NMK8Rj3zsUUiASpIe3Vyb/yDWTWttqgnaFVgwyy0JwwwTztzVk6jEReEsmNohL16JEDdRk9RQXblAtRXw/QYk9Gqc9TeLNE9YaDy0HcR3PEYbjK3EZsKqY6k13p2iaF8i+C+3vT+hXN7YwWoYXE94dYQnLaGrp5GYMdj59CIBKgE0ms9u0QrC0AdEwRORmvd01BQapDIhqiVjKBnFsyJpIYFzv013emx+qXCiSa91rNLtBrf3gSzI3717Jfye4d+nwMKrguYKZFBCG3PK73Lzl+vOJ6/W35pWPkNswnDl8vGPclLXjoSoIK0VoVHRYJF8vwlCzjv+deHRUZZ3hBFLqJO0QE68/hDOOOA+8LKD+14AFbLfNSxSIAKolsxjnZ6el2EpIgMQoA0Ox1lIwEqSKv3HZWbKmVao54RjVHCI3DhREY/ppyyrEwkQAVp3Y7qFVVPaz+iiMaolWh2NizMTI3I6EcNwZWDBKgg6hDFYfKAkiQy+lHPezlIgAqjnnAUkXNA8nzjUBBC/ZAAzRC1Q9UzO+aAdOWrJnIOCHd1OkpAAlQQueRxtDygEAFqe76VF508mgOqHxKggmgoJg6zwCAEtUFhRIZhayFqOUiACqKhmDhaQ3BaiJoWDTOaQdlwHJcHVAISoIJoKCaORqAHJOKIzAXXKl90FwlQQRSOG0dsEIIWIEcRPQQnuo8EqCBtAVI7VDkWGYSg6x5GoxHn9WZzQFKhbiMBmjFqiapmVqwDqr7o5An1gEJKrT8SoIK4bskwZsU6ILlAlRObCUFBCGUwqQCZ2VIz+7aZrTWzH5vZX5tZX37sfWb2t2PO/56ZDZjZbWa22sweMbMt+evVZtY/ThnfMrPDzewrZva7Y4691cyuMbM+M7vZzHp3Y+uFZrbZzO6Z8n+gIBqKiSMyCKEdfFJ90ckTuQ4I9KyXwW4FyLJu3uXAFe5+BHAksAD41GRf7O4nufvxwH8HLnX34/Ofh8aU8SKgx90fBC4GVoz5qhXAxe6+C7gB+I3dFHsRcPpktnUT3ZPV084FF6BA6njEER2EIA+o+0zmAZ0G7HD3rwC4+wjwYeD9Zja/Sza8G/h2/voG4GgzOwjAzPYGXgtckR+/Ij9/XNz9ZmBrl+zaLRqKiWM27Aek6149Fr4OSHSbyQToRcDKzg/c/QngEeAFXbLh5FYZucBdBrwzP/Zm4Ht5mQD3AC/pUrkzQkMxcTTyuzYmFY+IInYrdnlAZTDTIISJrsh0rtRBwJaO953DcCvy99mXZgK1y8wWTsfITszsHDMbNLPBLVu2TP4Hk37fjL9CTJPIXHBaEBJHI9+KPQJHz3oZTCZA9wEndn5gZvsAy4B1wM+B/cb8zf7AY9Ow4WlgXsf7fwcOMrPjgFcAV405fy6wYxrf/wzc/QJ3H3D3gSVLlhT9GrVDgYTmggOMoHGgxMnWAQUGIcgD6jqTCdANwHwzey+AmfUAnwMucvengNuBk83sufnxATKBWD8NG9bQMZznWZjLpcA/Ate4e1tszGwR8Ji7D03j+0tByUjjiMwFp6SUcVhoEILEpwx2K0C5GLwNeIeZrQUeIPM+/lt+fBPwIeBqM1sNnA+c5e7T6SJeBbx6zGcXA8fRMfyWcyrP9ojamNnFwK3AUWa2wczOnoYd00IpWeKIDsNWTziG6CE40X0mXFPTwt3XkwUDTHT824xGsY13/CKy8OiJ+BZwo5l9PJ/jwd1XM35H813Aebsp66zdlNNV2jek9KdyoheiyuuNITIIAQczyVC3Cc+E4O5PAx8HDtndefni1yvc/YFKDJsEJSONIzQXHJoLiCI0EwLqeJTBpB5QFbj7dVM4Zxfw1QrMmSKt7Rh0V1ZN9DogXfEYIrdjUCqecgj3gPZ01BhVT/QQnIgheg5Iz3r3kQAVRA1RHNFBCJqSjkELUeuHBKggCsOOwwI9IBSEEEbsdgyu614CEqCCjAYh6K6smtE5IAUhpIQFBiGArnsZSIAK0l4HJP2pnNAhOFdSyigit2PQkHs5SIAKop0x42gHIQRtx6CecAyxG9LFlFt3JEAzRQpUOeG54HTNQwhdiIo6HmUgASqIekRxxOeC08WPINsPKHAdkDoeXUcCVJDR/YB0V1ZNoxHnAYk44tcB6YbrNhKgomhr5jBCF6JqZ8ww4tcBiW4jASqIghDiCM0F56CFqDE0GpG54JSKpwwkQAVprwOSC1Q54bngdMlDiM0Fp+teBhKggrTngHRTVk5sLjj1hKOInAMCzQGVgQRI7HHE5oLTsGsUoXNAIaXWHwlQQbQfUByRueAUhh1HaC44XfJSkAAVRMlI44jNBaf1IFHE5oLT0GsZSIAKMtr4qTWqmp58Emg4qDVSQxRDT678I1EpmPSodx0JUEHkAcXR15PdtkMjzcrL1lBMHH29gdcddTzKQAJUFM0BhTF3Tnbb7hyKaohEBHN7A6+7sqCXggSoIKNh2Lotq2Zubw8AO4ejPCD1hCNodzyGRyovWx5QOUiAxB5Huycc0BChIIQwojseuu7dRwJUEIVhxxE7FKOecBSRHQ8tQC4HCVBBRlPxxNqRIr09DXoaxo6QhkidjihaArQjoOMhyqF2AmRmp5vZ/Wa2zszOK6uc0SBsNUcRzO1tBAUhqCccxdw5gUNwlZeYBrUSIDPrAb4IvAFYDpxlZsvLKKu1DkgeUAxzexshDRHomkfRCr8PmfvT0Gsp1EqAgJcC69z9QXffBVwCnFlGQboVY5nb2xM0F1B5kSJnNAouKPxeHY+u0xttQJc5BFjf8X4DcFIZBV38w0cA3ZRRLJjXy1V3bWTbU0PMndPD0HCTRiMbEvUJugcTDZdOdP54XH33z4B9i5gsZsjCuVlz9T+uvJdvHbIBgJERb2fGKPO6P7lzmF8O903HXDEF6iZAk2Jm5wDnACxbtqzw99zz6BPdMkkU4CO/diSfueZH/Ohn22lYtkq+M0PL2Cans6lx92et31I/YvbzggMW8K6TlnHT/Vu4e8Pj9PYYvQ1jpDl6Pcu47k/tyjztu588uLjxYlzqJkCPAod2vF+af9bG3S8ALgAYGBgoPKDSuo8VhBDDGccexBnHHlR5uf3nXVV5mSLDzPiLtx1bebm3P7SVd/z9rRp+LYG6zQHdDhxhZoeZWR+wAriyjIJam6JpCE6IetN61pWMp/vUygNy92Ez+yBwHdADXOju95ZRVsvzkQAJUW/a239IgLpOrQQIwN2vBq4uuxwNwQmRBqM78OpZ7zZ1G4KrjNatKA9IiHrTirJrqrPZdSRABZko6kYIUS9anUwFIXQfCVBBGvrPCZEEo+uM1N3sNmpGC6IgBCHSQEEI5SEBKsio8OimFKLOKAihPCRABWndlPKAhKg3o+uARLeRABWkpTuamBSi3rSj4OQBdR0JUFHa96IUSIg602gPc0iAuo0EqCCj48LBhgghSqWRe0Aj8oC6jnnCY0hmtgV4eAZfsRh4rEvm7Gmo7mmiuqfHTOv9PHdfMt6BpAVoppjZoLsPRNsRgequuqdGqnUvs94aghNCCBGCBEgIIUQIEqCZcUG0AYGo7mmiuqdHafXWHJAQQogQ5AEJIYQIQQI0BczsdDO738zWmdl54xyfa2aX5sdvM7P+ADNLYQp1/4iZ3Wdmd5nZDWb2vAg7y2Cyunec9+tm5mZWiwipqdTbzN6ZX/d7zewbVdtYFlO435eZ2Y1mdkd+z58RYWcZmNmFZrbZzO6Z4LiZ2d/k/5u7zOzFMy7U3fWzmx+yrb1/DBwO9AF3AsvHnPNfgL/PX68ALo22u8K6nwrMz1//fkp1z89bCNwM/AAYiLa7omt+BHAHsF/+/oBouyus+wXA7+evlwMPRdvdxfq/CngxcM8Ex88AriFLCfEy4LaZlikPaHJeCqxz9wfdfRdwCXDmmHPOBP4xf/0t4DVmtUhTOmnd3f1Gd38qf/sDYGnFNpbFVK47wJ8DnwV2VGlciUyl3r8DfNHdfwHg7psrtrEsplJ3B/bJX+8L/LRC+0rF3W8Gtu7mlDOBr3rGD4DnmNlBMylTAjQ5hwDrO95vyD8b9xx3HwYeBxZVYl25TKXunZxN1kOqA5PWPR+CONTdr6rSsJKZyjU/EjjSzP7NzH5gZqdXZl25TKXunwB+08w2AFcD/7Ua02YF020PJqV3RuYIkWNmvwkMAKdE21IFZtYAPg+8L9iUCHrJhuFeTebx3mxmx7r7tkijKuIs4CJ3/5yZvRz4mpkd4+7NaMP2ROQBTc6jwKEd75fmn417jpn1krnmP6/EunKZSt0xs9cCfwq8xd13VmRb2UxW94XAMcD3zOwhsjHxK2sQiDCVa74BuNLdh9z9J8ADZIK0pzOVup8N/BOAu98KzCPLlZYCU2oPpoMEaHJuB44ws8PMrI8syODKMedcCfxW/vrtwL96Pmu3hzNp3c3sBOD/kolPXeYCYJK6u/vj7r7Y3fvdvZ9s/ust7j4YY27XmMr9fgWZ94OZLSYbknuwQhvLYip1fwR4DYCZvZBMgLZUamUcVwLvzaPhXgY87u4bZ/KFGoKbBHcfNrMPAteRRclc6O73mtkngUF3vxL4Mpkrvo5sEm9FnMXdY4p1/1/AAuCbedzFI+7+ljCju8QU6147pljv64DXmdl9wAjwh+6+x3v8U6z7R4EvmdmHyQIS3leTziZmdjFZx2JxPsf1cWAOgLv/Pdmc1xnAOuAp4D/PuMya/O+EEELsYWgITgghRAgSICGEECFIgIQQQoQgARJCCBGCBEgIIRJksuSjBb7vL/PktGvypKWTpiOTAAkhRJpcBHQljZKZvQI4GfgVsgXaL2EKWVEkQEKUhJktMrPV+c/PzOzR/PWTZvZ3JZV5rpm9N3/9snx7kNV5r/QT+edvyte2iIQZL/momT3fzK41s5Vm9n0zO3qqX0e2KLcPmEu2fmjTZH+kdUBCVEDe+D/p7n9VYhm9wCrgxfmiyvuBd7r7nWbWAxzl7vflQyOrgJM7MpmLBLFs77L/7+7H5O9vAH7P3dea2UnAp939tCl+118Bv022XcPfuvufTvY3yoQgRMWY2auBP3D3N+XCdBjZHjTLgA+T5ZV7A1merTe7+5CZnUiW/HQB8BjZCvyxaVBOA1blGdkBDgA2Arj7CHBf/trN7HvAm8jzmglhZguAVzCa1QQybwYz+0/AeF7zo+7+ejN7AfBCRrdj+a6ZvdLdv7+7MjUEJ0Q8zycTj7cA/w+40d2PBZ4G3mhmc4AvAG939xOBC4FPjfM9JwMrO97/b+B+M/tnM/tdM5vXcWwQeGX3qyL2YBrANnc/vuPnhQDufrm7HzPOz+vzv30b8AN3f9LdnyTbluXlUylQCBHLNe4+BNxNloPs2vzzu4F+4Ciyid3vmtlq4M8Yf+O/g+hIjOnunyTbIuM7wLs6vhdgM3BwNysh9mzc/QngJ2b2DmhvwX3cFP/8EeAUM+vNO0ynAGsm+yMNwQkRz04Ad2+a2VBHcssm2TNqwL3uPlmP8mmyieA27v5j4P+Y2ZeALWa2KE8cOi8/XyTKBMlH3012v/wZWSDBJWRbk0/Gt8i8+LvJAhKudfd/meyPJEBCzH7uB5aY2cvd/da8h3mku9875rw1wAtab8zsjcDVuaAdQZa5elt++EigK+s/xJ6Ju581waFph2bnc4y/O92/0xCcELMcd99Fts/UZ83sTmA12WTxWK4BXtXx/j1kc0Crga8B784bCoBTgTptJS72QBSGLUSNMLN/Bv7I3dfu5pwDgW+4+2uqs0yIZyMBEqJGmNlRwIH5IsOJznkJMOTuqyszTIhxkAAJIYQIQXNAQgghQpAACSGECEECJIQQIgQJkBBCiBAkQEIIIUL4D4WkNXe2mJg4AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "a, b, out = Net(\"A\"), Net(\"B\"), Net(\"OUT\")\n",
    "\n",
    "# Create two square waves: a at 500 MHz and b at 250 MHz.\n",
    "cntgen(a, b)\n",
    "\n",
    "# Create a NAND gate and connect its I/O to the nets.\n",
    "nand()[\"a, b, out\"] += a, b, out\n",
    "\n",
    "# Perform a transient analysis.\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=10@u_ns)\n",
    "oscope(waveforms, a, b, out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The NAND gate output only goes low when both inputs are high, as expected. Ho hum."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## One or the Other: the XOR Gate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Continuing on, here is the last combinational gate I'll do: the exclusive-OR. There's nothing really new here that you haven't already seen with the NAND gate, just more of it."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![XOR gate](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2Ff%2Ffa%2FCMOS_XOR_Gate.svg%2F1280px-CMOS_XOR_Gate.svg.png&f=1&nofb=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:54:16.028292Z",
     "start_time": "2021-04-30T19:54:16.005662Z"
    }
   },
   "outputs": [],
   "source": [
    "@package\n",
    "def xor(a=Net(), b=Net(), out=Net()):\n",
    "    # Create eight transistors: four NFETs and four PFETs.\n",
    "    qn_a, qn_ab, qn_b, qn_bb = nfet(4)\n",
    "    qp_a, qp_ab, qp_b, qp_bb = pfet(4)\n",
    "    \n",
    "    # Connect the substrates of the transistors.\n",
    "    vdd & qp_a.b & qp_ab.b & qp_b.b & qp_bb.b\n",
    "    gnd & qn_a.b & qn_ab.b & qn_b.b & qn_bb.b\n",
    "    \n",
    "    # Create the two parallel \"legs\" of series PFETs-NFETs with a\n",
    "    # common output node in the middle.\n",
    "    vdd & qp_ab[\"s,d\"] & qp_b[\"s,d\"] & out & qn_a[\"d,s\"] & qn_b[\"d,s\"] & gnd\n",
    "    vdd & qp_a[\"s,d\"] & qp_bb[\"s,d\"] & out & qn_ab[\"d,s\"] & qn_bb[\"d,s\"] & gnd\n",
    "    \n",
    "    # Create two inverters to get the complements of both inputs.\n",
    "    ab, bb = inverter(), inverter()\n",
    "    ab.a += a\n",
    "    bb.a += b\n",
    "\n",
    "    # Attach the two inputs and their complements to the transistor gates.\n",
    "    a      & qp_a.g  & qn_a.g\n",
    "    ab.out & qp_ab.g & qn_ab.g\n",
    "    b      & qp_b.g  & qn_b.g\n",
    "    bb.out & qp_bb.g & qn_bb.g\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:54:48.159865Z",
     "start_time": "2021-04-30T19:54:16.030512Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "a, b, out = Net(\"A\"), Net(\"B\"), Net(\"OUT\")\n",
    "cntgen(a, b)\n",
    "\n",
    "xor()[\"a, b, out\"] += a, b, out\n",
    "\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=10@u_ns)\n",
    "oscope(waveforms, a, b, out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The output only goes high when the inputs have opposite values, so the XOR gate is working correctly."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## No, It's Not a Snake: The Adder"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally I've reached the level of abstraction where individual transistors aren't needed. I can use the gates I've already built to construct new stuff, like this [full-adder bit](https://www.geeksforgeeks.org/full-adder-in-digital-logic/):"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Full adder bit](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse4.mm.bing.net%2Fth%3Fid%3DOIP.hv1H5z95bT2f_llqtxYglQHaEt%26pid%3DApi&f=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:54:48.180543Z",
     "start_time": "2021-04-30T19:54:48.161296Z"
    }
   },
   "outputs": [],
   "source": [
    "@package\n",
    "def full_adder(a=Net(), b=Net(), cin=Net(), s=Net(), cout=Net()):\n",
    "    # Use two XOR gates to compute the sum bit.\n",
    "    ab_sum = Net()  # Net to carry the intermediate result of a+b.\n",
    "    xor()[\"a,b,out\"] += a, b, ab_sum    # Compute ab_sum=a+b\n",
    "    xor()[\"a,b,out\"] += ab_sum, cin, s  # Compute s=a+b+cin\n",
    "    \n",
    "    # Through the magic of DeMorgan's Theorem, the AND-OR carry circuit\n",
    "    # can be done using three NAND gates.\n",
    "    nand1, nand2, nand3 = nand(), nand(), nand()\n",
    "    nand1[\"a,b\"] += ab_sum, cin\n",
    "    nand2[\"a,b\"] += a, b\n",
    "    nand3[\"a,b,out\"] += nand1.out, nand2.out, cout"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "I'll use a `cntgen()` with three outputs to apply all eight input combinations to the full-adder:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:21.093469Z",
     "start_time": "2021-04-30T19:54:48.181998Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "# Generate nets for the inputs and outputs.\n",
    "a, b, cin, s, cout = Net(\"A\"), Net(\"B\"), Net(\"CIN\"), Net(\"S\"), Net(\"COUT\")\n",
    "\n",
    "# Drive the A, B and CIN full-adder inputs with all eight combinations.\n",
    "cntgen(a, b, cin)\n",
    "\n",
    "# Connect the I/O nets to the full-adder.\n",
    "full_adder()[\"a, b, cin, s, cout\"] += a, b, cin, s, cout\n",
    "\n",
    "# Do a transient analysis.\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=8@u_ns)\n",
    "oscope(waveforms, a, b, cin, s, cout)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The sum and carry-out bits of the full-adder match the truth-table for all the combinations of A, B and the carry input."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now I'll combine multiple full-adders to build a multi-bit adder:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:21.123092Z",
     "start_time": "2021-04-30T19:55:21.094985Z"
    }
   },
   "outputs": [],
   "source": [
    "@subcircuit\n",
    "def adder(a, b, cin, s, cout):\n",
    "    # a, b and s are multi-bit buses. The width of the adder will\n",
    "    # be determined by the length of the sum output.\n",
    "    width = len(s)\n",
    "    \n",
    "    # Create a list of full-adders equal to the width of the sum output.\n",
    "    fadds = [full_adder() for _ in range(width)]\n",
    "    \n",
    "    # Iteratively connect the full-adders to the input and output bits.\n",
    "    for i in range(width):\n",
    "        \n",
    "        # Connect the i'th full adder to the i'th bit of a, b and s.\n",
    "        fadds[i][\"a, b, s\"] += a[i], b[i], s[i]\n",
    "        \n",
    "        if i == 0:\n",
    "            # Connect the carry input to the first full-adder.\n",
    "            fadds[i].cin += cin\n",
    "        else:\n",
    "            # Connect the carry input of the rest of the full-adders\n",
    "            # to the carry output from the previous one.\n",
    "            fadds[i].cin += fadds[i-1].cout\n",
    "            \n",
    "    # Connect the carry output to the carry output from the last bit of the adder.\n",
    "    cout += fadds[-1].cout"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "I'll instantiate a two-bit adder and test it with all 32 input combinations of A$_0$, A$_1$, B$_0$, B$_1$, and C$_{in}$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:56.439440Z",
     "start_time": "2021-04-30T19:55:21.126142Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 8 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "# Create the two-bit input and output buses and the carry input & output nets.\n",
    "w = 2\n",
    "a, b, cin, s, cout = Bus(\"A\",w), Bus(\"B\",w), Net(\"CIN\"), Bus(\"S\",w), Net(\"COUT\")\n",
    "\n",
    "# Drive the A0, A1, B0, B1, and CIN inputs with a five-bit counter.\n",
    "cntgen(*a, *b, cin)\n",
    "\n",
    "# Connect the I/O to an adder.\n",
    "adder(a, b, cin, s, cout)\n",
    "\n",
    "# Do a transient analysis\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=32@u_ns)\n",
    "oscope(waveforms, *a, *b, cin, *s, cout)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The outputs *look* like they might be correct, but I'm not going to waste my time trying to eyeball it when Python can do that. The following code subsamples the waveforms and converts them into a table of integers for the adder's inputs and outputs:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:56.473311Z",
     "start_time": "2021-04-30T19:55:56.440672Z"
    }
   },
   "outputs": [],
   "source": [
    "def integerize(waveforms, *nets, threshold=0.9@u_V):\n",
    "    \"\"\"\n",
    "    Convert a set of N waveforms to a stream of N-bit integer values.\n",
    "    \n",
    "    Args:\n",
    "        waveforms: Waveform data from ngspice.\n",
    "        nets: A set of nets comprising a digital word.\n",
    "        threshold: Voltage threshold for determining if a waveform value is 1 or 0.\n",
    "        \n",
    "    Returns:\n",
    "        A list of integer values, one for each sample time in the waveform data.\n",
    "    \"\"\"\n",
    "    \n",
    "    def binarize():\n",
    "        \"\"\"Convert multiple waveforms into streams of ones and zeros.\"\"\"\n",
    "        binary_vals = []\n",
    "        for net in nets:\n",
    "            binary_vals.append([v > threshold for v in waveforms[node(net)]])\n",
    "        return binary_vals\n",
    "\n",
    "    # Convert the waveforms into streams of bits, then combine the bits into integers.\n",
    "    int_vals = []\n",
    "    for bin_vector in zip(*reversed(binarize())):\n",
    "        int_vals.append(int(bytes([ord('0')+b for b in bin_vector]), base=2))\n",
    "    return int_vals\n",
    "\n",
    "def subsample(subsample_times, sample_times, *int_waveforms):\n",
    "    \"\"\"\n",
    "    Take a subset of samples from a set of integerized waveforms at a set of specific times.\n",
    "    \n",
    "    Args:\n",
    "        subsample_times: A list of times (in ascending order) at which to take subsamples.\n",
    "        sample_times: A list of times (in ascending order) for when each integerized sample was taken.\n",
    "        int_waveforms: List of integerized waveform sample lists.\n",
    "        \n",
    "    Returns:\n",
    "        A list of subsample lists.\n",
    "    \"\"\"\n",
    "    \n",
    "    # Create a list of the empty lists to hold the subsamples from each integerized waveform.\n",
    "    subsamples = [[] for _ in int_waveforms]\n",
    "    \n",
    "    # Get the first subsample time.\n",
    "    subsample_time = subsample_times.pop(0)\n",
    "    \n",
    "    # Step through the sample times, looking for the time to take a subsample.\n",
    "    for sample_time, *samples in zip(sample_times, *int_waveforms):\n",
    "        \n",
    "        # Take a subsample whenever the sample time is less than the current subsample time.\n",
    "        if sample_time > subsample_time:\n",
    "        \n",
    "            # Store a subsample from each waveform.\n",
    "            for i, v in enumerate(samples):\n",
    "                subsamples[i].append(v)\n",
    "                \n",
    "            # Get the next subsample time and break from loop if there isn't one.\n",
    "            try:\n",
    "                subsample_time = subsample_times.pop(0)\n",
    "            except IndexError:\n",
    "                break\n",
    "\n",
    "    return subsamples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:56.688417Z",
     "start_time": "2021-04-30T19:55:56.474528Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>CIN</th>\n",
       "      <th>S</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>28</th>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29</th>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31</th>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    A  B  CIN  S\n",
       "0   0  0    0  0\n",
       "1   1  0    0  1\n",
       "2   2  0    0  2\n",
       "3   3  0    0  3\n",
       "4   0  1    0  1\n",
       "5   1  1    0  2\n",
       "6   2  1    0  3\n",
       "7   3  1    0  4\n",
       "8   0  2    0  2\n",
       "9   1  2    0  3\n",
       "10  2  2    0  4\n",
       "11  3  2    0  5\n",
       "12  0  3    0  3\n",
       "13  1  3    0  4\n",
       "14  2  3    0  5\n",
       "15  3  3    0  6\n",
       "16  0  0    1  1\n",
       "17  1  0    1  2\n",
       "18  2  0    1  3\n",
       "19  3  0    1  4\n",
       "20  0  1    1  2\n",
       "21  1  1    1  3\n",
       "22  2  1    1  4\n",
       "23  3  1    1  5\n",
       "24  0  2    1  3\n",
       "25  1  2    1  4\n",
       "26  2  2    1  5\n",
       "27  3  2    1  6\n",
       "28  0  3    1  4\n",
       "29  1  3    1  5\n",
       "30  2  3    1  6\n",
       "31  3  3    1  7"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Convert the waveforms for A, B, Cin, S, and Cout into lists of integers.\n",
    "a_ints = integerize(waveforms, *a)\n",
    "b_ints = integerize(waveforms, *b)\n",
    "cin_ints = integerize(waveforms, cin)\n",
    "# Combine the N-bit sum and carry-out into a single N+1-bit integer.\n",
    "s_ints = integerize(waveforms, *s, cout)\n",
    "\n",
    "# Set the subsample times just before the adder's inputs change.\n",
    "ts = [(i+0.9)@u_ns for i in range(32)]\n",
    "\n",
    "# Subsample the integerized adder waveforms.\n",
    "av, bv, cinv, sv = subsample(ts, waveforms.time, a_ints, b_ints, cin_ints, s_ints)\n",
    "\n",
    "# Display a table of the adder's inputs and corresponding output.\n",
    "pd.DataFrame({'A': av, 'B': bv, 'CIN': cinv, 'S': sv})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "That's better, but even checking all the table entries is too much work so I'll write a little code to do that:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:56.705012Z",
     "start_time": "2021-04-30T19:55:56.689605Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "No errors found.\n"
     ]
    }
   ],
   "source": [
    "error_flag = False\n",
    "for a, b, cin, s in zip(av, bv, cinv, sv):\n",
    "    if a+b+cin != s:\n",
    "        print(f\"ERROR: {a}+{b}+{cin} != {s}\")\n",
    "        error_flag = True\n",
    "if not error_flag:\n",
    "    print(\"No errors found.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "OK, at this point I'm convinced I have a working two-bit adder. And I can make any size adder I want just by changing the input and output bus widths.\n",
    "\n",
    "Onward!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fragments of Memory: Latches, Flip-Flops and Registers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cross-coupled logic gates like this [dynamic master-slave flip-flop](http://ece-research.unm.edu/jimp/vlsi/slides/chap5_2.html) are often used for storing bits:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Dynamic latch bit](http://ece-research.unm.edu/jimp/vlsi/slides/chap5_2-22.gif)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A problem with this circuit is the use of NMOS FETs as pass gates for the input and feedback latch. Because I'm using 1.8V as my supply voltage, any logic-high signal passing through the NMOS FET is reduced by the approximately 0.6V threshold voltage to around 1.2V. While this is workable, it does lead to some increased propagation delay. Therefore, I built a transmission gate that parallels the NMOS FET with a PMOS FET with the gate of each being driven by complementary signals. This allows signals to pass through without being degraded by the threshold voltage.\n",
    "<a id=\"tx_gate\"/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:56.724353Z",
     "start_time": "2021-04-30T19:55:56.706382Z"
    }
   },
   "outputs": [],
   "source": [
    "@package\n",
    "def tx_gate(i, g, g_b, o):\n",
    "    \"\"\"NMOS/PMOS transmission gate. When g is high and g_b is low, i and o are connected.\"\"\"\n",
    "    \n",
    "    # NMOS and PMOS transistors for passing input to output.\n",
    "    qn, qp = nfet(), pfet()\n",
    "    \n",
    "    # Transistor substrate connections.\n",
    "    gnd & qn.b\n",
    "    vdd & qp.b\n",
    "    \n",
    "    # Parallel NMOS/PMOS transistors between the input and output.\n",
    "    i & (qn[\"s,d\"] | qp[\"s,d\"]) & o\n",
    "    \n",
    "    # Connect the gate input to the NMOS and the complement of the gate input\n",
    "    # to the PMOS. Both transistors will conduct when the gate input is high,\n",
    "    # and will block the input from the output when the gate input is low.\n",
    "    g & qn.g\n",
    "    g_b & qp.g"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The SKiDL implementation for half of this flip-flop creates a latch that allows data to enter and pass through when the write-enable is active, and then latches the data bit with a feedback gate when the write-enable is not asserted:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:56.744241Z",
     "start_time": "2021-04-30T19:55:56.725657Z"
    }
   },
   "outputs": [],
   "source": [
    "@package\n",
    "def latch_bit(wr=Net(), wr_b=Net(), d=Net(), out_b=Net()):\n",
    "    \n",
    "    in_tx, fb_tx = tx_gate(), tx_gate()\n",
    "    in_inv, fb_inv = inverter(), inverter()\n",
    "    \n",
    "    # Input data comes in through the input gate, goes through an inverter to the data output.\n",
    "    d & in_tx[\"i,o\"] & in_inv[\"a, out\"] & out_b\n",
    "\n",
    "    # The data output is fed back through another inverter and transmission gate to the input inverter.  \n",
    "    out_b & fb_inv[\"a, out\"] & fb_tx[\"i,o\"] & in_inv.a  # Feed output back to input.\n",
    "    \n",
    "    # wr activates the input gate and deactivates the feedback gate, allowing data into the latch.\n",
    "    wr & in_tx.g & fb_tx.g_b\n",
    "\n",
    "    # Complement of wr deactivates the input gate and activates the feedback gate, latching the data.\n",
    "    wr_b & in_tx.g_b & fb_tx.g"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By cascading two of these latches, I arrive at the complete flip-flop:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:55:56.764441Z",
     "start_time": "2021-04-30T19:55:56.745465Z"
    }
   },
   "outputs": [],
   "source": [
    "@package\n",
    "def ms_ff(wr=Net(), d=Net(), out=Net()):\n",
    "    \n",
    "    # Create the master and slave latches.\n",
    "    master, slave = latch_bit(), latch_bit()\n",
    "    \n",
    "    # Data passes from the input through the master to the slave latch and then to the output.\n",
    "    d & master[\"d, out_b\"] & slave[\"d, out_b\"] & out\n",
    "    \n",
    "    # Data continually enters the master latch when the write-enable is low, but gets \n",
    "    # latched when the write-enable goes high..\n",
    "    wr & inverter()[\"a, out\"] & master.wr & slave.wr_b\n",
    "    \n",
    "    # Data from the master passes through the slave when the write-enable goes high, and\n",
    "    # this data stays stable in the slave when the write-enable goes low and new data \n",
    "    # is entering the master.\n",
    "    wr & slave.wr & master.wr_b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A simple test shows the flip-flop retains data and the output only changes upon the rising edge of the write-enable (after a small propagation delay):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:56:29.335709Z",
     "start_time": "2021-04-30T19:55:56.765550Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "wr, d, out = Net('WR'), Net('D'), Net('OUT')\n",
    "cntgen(wr, d)\n",
    "\n",
    "ms_ff()[\"wr, d, out\"] += wr, d, out\n",
    "\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=8@u_ns)\n",
    "oscope(waveforms, wr, d, out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once I have a basic flip-flop, it's easy to build multi-bit registers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:56:29.356870Z",
     "start_time": "2021-04-30T19:56:29.337092Z"
    }
   },
   "outputs": [],
   "source": [
    "@subcircuit\n",
    "def register(wr, d, out):\n",
    "\n",
    "    # Create a flip-flop for each bit in the output bus.\n",
    "    reg_bits = [ms_ff() for _ in out]\n",
    "    \n",
    "    # Connect the inputs and outputs to the flip-flops.\n",
    "    for i, rb in enumerate(reg_bits):\n",
    "        rb[\"wr, d, out\"] += wr, d[i], out[i]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Simplest State Machine: the Counter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With both an adder and a register in hand, a counter is the obvious next step:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:56:29.375097Z",
     "start_time": "2021-04-30T19:56:29.358147Z"
    }
   },
   "outputs": [],
   "source": [
    "@subcircuit\n",
    "def cntr(clk, out):\n",
    "    # Create two buses: one for the next counter value, and one that's all zero bits.\n",
    "    width = len(out)\n",
    "    nxt, zero = Bus(width), Bus(width)\n",
    "    \n",
    "    # Provide access to the global ground net.\n",
    "    global gnd\n",
    "    \n",
    "    # Connect all the zero bus bits to ground (that's why it's zero).\n",
    "    gnd += zero\n",
    "\n",
    "    # The next counter value is the current counter value plus 1. Set the\n",
    "    # adder's carry input to 1 and the b input to zero to do this.\n",
    "    adder(a=out, b=zero, cin=vdd, s=nxt, cout=Net())\n",
    "    \n",
    "    # Clock the next counter value into the register on the rising clock edge.\n",
    "    register(wr=clk, d=nxt, out=out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now just give it a clock and watch it go!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:57:08.355434Z",
     "start_time": "2021-04-30T19:56:29.376827Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "# Generate a clock signal.\n",
    "clk = Net('clk')\n",
    "cntgen(clk)\n",
    "\n",
    "# Create a three-bit counter.\n",
    "cnt = Bus('CNT', 3)\n",
    "cntr(clk, cnt)\n",
    "\n",
    "# Simulate the counter.\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=30@u_ns)\n",
    "\n",
    "# In addition to the clock and counter value, also look at the power supply current.\n",
    "disp_imin, disp_imax = -3@u_mA, 3@u_mA\n",
    "oscope(waveforms, clk, *cnt, vdd_ps)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Looking at the counter bits shows its obviously incrementing 0, 1, 2, ..., 7, 0, ... The bottom trace shows the pulses of supply current on every clock edge. (Remember that whole current-pulse-during-input-transition thing?) But how much energy is being used? Multiplying the supply current by its output voltage and summing over time will answer that:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:57:08.398895Z",
     "start_time": "2021-04-30T19:57:08.358199Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total energy = 3.2599093374096875e-12 J\n"
     ]
    }
   ],
   "source": [
    "time_steps = waveforms.time[1:] - waveforms.time[0:-1]\n",
    "ps_current = -waveforms[node(vdd_ps)][0:-1] # Mult by -1 to get current FROM the + terminal of the supply.\n",
    "ps_voltage = waveforms[node(vdd)][0:-1]\n",
    "\n",
    "energy = sum(ps_current * ps_voltage * time_steps)@u_J\n",
    "print(f\"Total energy = {energy}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As for the total number of transistors in the counter ..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:57:08.415867Z",
     "start_time": "2021-04-30T19:57:08.400391Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V: 1\n",
      "PULSEV: 1\n",
      "sky130_fd_pr__nfet_01v8: 81\n",
      "sky130_fd_pr__pfet_01v8: 81\n"
     ]
    }
   ],
   "source": [
    "how_big()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bonus: an ALU"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An adder is great and all, but that's all it does: adds. Having a module that adds, subtracts, shifts, and performs logical operations is much cooler! That's an *arithmetic logic unit* (ALU).\n",
    "\n",
    "You might think building an ALU is a lot harder than building an adder, but it's not. It can all be done using an *8-to-1 multiplexer* (mux) as the basic building block:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![8-to-1 Multiplexer](https://www.researchgate.net/profile/Senentxu_Lanceros-Mendez/publication/224311777/figure/fig4/AS:393728339529731@1470883559740/81-analog-multiplexer-circuit.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, if you look *real hard* at the circuit above, you'll realize you can smash the sixteen legs of series NMOS/PMOS transistors into just eight legs of series transmission gates like the one I used [above](#tx_gate)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "I can build a full-adder bit from a pair of 8-to-1 muxes by passing the A, B, and C$_{in}$ inputs as the selectors, and applying the eight-bit truth-table for the S and C$_{out}$ bits to the input of each mux, respectively. Then I'll combine the full-adder bits to build a complete $N$-bit adder as before.\n",
    "\n",
    "But I can also build a subtractor, left-shifter, logical-AND, etc just by changing the truth-table bits that go to each mux. (If you're familiar with [FPGAs](https://en.wikipedia.org/wiki/Field-programmable_gate_array), the mux is essentially the same as their [look-up tables](https://electronics.stackexchange.com/questions/169532/what-is-an-lut-in-fpga).)\n",
    "\n",
    "The complete SKiDL code for an ALU is shown below. (Much easier to create, thankfully, than tediously drawing the circuit shown above.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:57:08.446717Z",
     "start_time": "2021-04-30T19:57:08.418029Z"
    }
   },
   "outputs": [],
   "source": [
    "@package\n",
    "def mux8(in_, i0=Net(), i1=Net(), i2=Net(), out=Net()):\n",
    "    \n",
    "    # Create the complements of the selection inputs.\n",
    "    i0b, i1b, i2b = Net(), Net(), Net()\n",
    "    i0 & inverter()[\"a,out\"] & i0b\n",
    "    i1 & inverter()[\"a,out\"] & i1b\n",
    "    i2 & inverter()[\"a,out\"] & i2b\n",
    "\n",
    "    out_ = Net()  # Output from the eight legs of the mux.\n",
    "    i = 0  # Input bit index.\n",
    "    \n",
    "    # Create the eight legs of the mux by nested iteration of the selection inputs\n",
    "    # and their complements. Each leg is turned on by a different combination of inputs.\n",
    "    for i2_g, i2_g_b in ((i2b, i2), (i2, i2b)):\n",
    "        for i1_g, i1_g_b in ((i1b, i1), (i1, i1b)):\n",
    "            for i0_g, i0_g_b in ((i0b, i0), (i0, i0b)):\n",
    "                \n",
    "                # Place 3 transmission gates in series from input bit i to output.\n",
    "                i0_gate, i1_gate, i2_gate = tx_gate(), tx_gate(), tx_gate()\n",
    "                in_[i] & i0_gate[\"i,o\"] & i1_gate[\"i,o\"] & i2_gate[\"i,o\"] & out_\n",
    "                \n",
    "                # Attach the selection inputs and their complements to the transmission gates.\n",
    "                i0_gate[\"g, g_b\"] += i0_g, i0_g_b\n",
    "                i1_gate[\"g, g_b\"] += i1_g, i1_g_b\n",
    "                i2_gate[\"g, g_b\"] += i2_g, i2_g_b\n",
    "                \n",
    "                i = i+1  # Go to the next input bit.\n",
    "                \n",
    "    # Run the output through two inverters to restore signal strength.\n",
    "    out_ & inverter()[\"a, out\"] & inverter()[\"a, out\"] & out\n",
    "                \n",
    "@subcircuit\n",
    "def alu(a, b, cin, s, cout, s_opcode, c_opcode):\n",
    "    \"\"\"\n",
    "    Multi-bit ALU with the operation determined by the eight-bit codes\n",
    "    that determine the output from the sum and carry muxes.\n",
    "    \"\"\"\n",
    "    \n",
    "    width = len(s)\n",
    "    s_bits = [mux8() for _ in range(width)]\n",
    "    c_bits = [mux8() for _ in range(width)]\n",
    "    \n",
    "    # For each bit in the ALU...\n",
    "    for i in range(width):\n",
    "        \n",
    "        # Connect truth-table bits to the sum and carry mux inputs.\n",
    "        s_bits[i].in_ += s_opcode\n",
    "        c_bits[i].in_ += c_opcode\n",
    "        \n",
    "        # Connect inputs to the sum and carry mux selectors.\n",
    "        s_bits[i][\"i0, i1\"] += a[i], b[i]\n",
    "        c_bits[i][\"i0, i1\"] += a[i], b[i]\n",
    "        \n",
    "        # Connect the carry input of each ALU bit to the carry output of the previous bit.\n",
    "        if i == 0:\n",
    "            s_bits[i].i2 & cin\n",
    "            c_bits[i].i2 & cin\n",
    "        else:\n",
    "            s_bits[i].i2 & c_bits[i-1].out\n",
    "            c_bits[i].i2 & c_bits[i-1].out\n",
    "            \n",
    "        # Connect the output bit of each sum mux to the ALU sum output.\n",
    "        s[i] & s_bits[i].out\n",
    "        \n",
    "    # Connect the carry output from the last ALU bit.\n",
    "    cout & c_bits[-1].out"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By setting the sum and carry opcodes appropriately, I can build a subtractor from the ALU:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:57:08.469069Z",
     "start_time": "2021-04-30T19:57:08.448599Z"
    }
   },
   "outputs": [],
   "source": [
    "@subcircuit\n",
    "def subtractor(a, b, cin, s, cout):\n",
    "    \"\"\"\n",
    "    Create a subtractor by applying the required opcodes to the ALU.\n",
    "    \"\"\"\n",
    "\n",
    "    # Set the opcodes to perform subtraction (a - b - c), so in reality the carry\n",
    "    # is actually a borrow.\n",
    "    # cin  b   a   s  cout\n",
    "    # ====================\n",
    "    #  0   0   0   0   0\n",
    "    #  0   0   1   1   0\n",
    "    #  0   1   0   1   1\n",
    "    #  0   1   1   0   0\n",
    "    #  1   0   0   1   1\n",
    "    #  1   0   1   0   0\n",
    "    #  1   1   0   0   1\n",
    "    #  1   1   1   1   1\n",
    "    one = vdd\n",
    "    zero = gnd\n",
    "    s_opcode = Bus(zero, one, one, zero, one, zero, zero, one)\n",
    "    c_opcode = Bus(zero, zero, one, zero, one, zero, one, one)\n",
    "\n",
    "    # Connect the I/O and opcodes to the ALU.\n",
    "    alu(a=a, b=b, cin=cin, s=s, cout=cout, s_opcode=s_opcode, c_opcode=c_opcode)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now I'll test the subtractor just as I did previously with the adder:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:57:52.220846Z",
     "start_time": "2021-04-30T19:57:08.470390Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>CIN</th>\n",
       "      <th>S</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>3</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>28</th>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29</th>\n",
       "      <td>1</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>30</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>31</th>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    A  B  CIN  S\n",
       "0   0  0    0  0\n",
       "1   1  0    0  1\n",
       "2   2  0    0  2\n",
       "3   3  0    0  3\n",
       "4   0  1    0  7\n",
       "5   1  1    0  0\n",
       "6   2  1    0  1\n",
       "7   3  1    0  2\n",
       "8   0  2    0  6\n",
       "9   1  2    0  7\n",
       "10  2  2    0  0\n",
       "11  3  2    0  1\n",
       "12  0  3    0  5\n",
       "13  1  3    0  6\n",
       "14  2  3    0  7\n",
       "15  3  3    0  0\n",
       "16  0  0    1  7\n",
       "17  1  0    1  0\n",
       "18  2  0    1  1\n",
       "19  3  0    1  2\n",
       "20  0  1    1  6\n",
       "21  1  1    1  7\n",
       "22  2  1    1  0\n",
       "23  3  1    1  1\n",
       "24  0  2    1  5\n",
       "25  1  2    1  6\n",
       "26  2  2    1  7\n",
       "27  3  2    1  0\n",
       "28  0  3    1  4\n",
       "29  1  3    1  5\n",
       "30  2  3    1  6\n",
       "31  3  3    1  7"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 8 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "# Create the two-bit input and output buses and the carry input & output nets.\n",
    "w = 2\n",
    "a, b, cin, s, cout = Bus(\"A\",w), Bus(\"B\",w), Net(\"CIN\"), Bus(\"S\",w), Net(\"COUT\")\n",
    "\n",
    "# Drive the A0, A1, B0, B1, and CIN inputs with a five-bit counter.\n",
    "cntgen(*a, *b, cin)\n",
    "\n",
    "# Connect the I/O to the subtractor.\n",
    "subtractor(a=a, b=b, cin=cin, s=s, cout=cout)\n",
    "\n",
    "# Do a transient analysis\n",
    "disp_vmax = 4@u_V\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=32@u_ns)\n",
    "\n",
    "# Display the output waveforms.\n",
    "oscope(waveforms, *a, *b, cin, *s, cout)\n",
    "\n",
    "# Convert the waveforms for A, B, Cin, S, and Cout into lists of integers.\n",
    "a_ints = integerize(waveforms, *a)\n",
    "b_ints = integerize(waveforms, *b)\n",
    "cin_ints = integerize(waveforms, cin)\n",
    "# Combine the N-bit sum and carry-out into a single N+1-bit integer.\n",
    "s_ints = integerize(waveforms, *s, cout)\n",
    "\n",
    "# Set the subsample times right before the ALU's inputs change.\n",
    "ts = [(i+0.9)@u_ns for i in range(32)]\n",
    "\n",
    "# Subsample the integerized ALU waveforms.\n",
    "av, bv, cinv, sv = subsample(ts, waveforms.time, a_ints, b_ints, cin_ints, s_ints)\n",
    "\n",
    "# Display a table of the ALU's inputs and corresponding output.\n",
    "pd.DataFrame({'A': av, 'B': bv, 'CIN': cinv, 'S': sv})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extra Bonus: a Down Counter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since I went to the trouble to build a subtractor, it would be a waste if I didn't use it to make a down-counter:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:57:52.244025Z",
     "start_time": "2021-04-30T19:57:52.223975Z"
    }
   },
   "outputs": [],
   "source": [
    "@subcircuit\n",
    "def down_cntr(clk, out):\n",
    "    # Provide access to the global ground net.\n",
    "    global gnd\n",
    "    \n",
    "    width = len(out)\n",
    "    nxt, zero = Bus(width), Bus(width)\n",
    "    \n",
    "    gnd += zero\n",
    "\n",
    "    # The next counter value is the current counter value minus 1. Set the\n",
    "    # subtractor's borrow input to 1 and the b input to zero to do this.\n",
    "    subtractor(a=out, b=zero, cin=vdd, s=nxt, cout=Net())\n",
    "    \n",
    "    register(wr=clk, d=nxt, out=out)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:58:47.505980Z",
     "start_time": "2021-04-30T19:57:52.245250Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "No errors or warnings found during netlist generation.\n",
      "\n",
      "Warning: include: has no value, DC 0 assumed\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pwr()\n",
    "\n",
    "clk = Net('clk')\n",
    "cntgen(clk)\n",
    "\n",
    "# Create a three-bit down counter.\n",
    "cnt = Bus('CNT', 3)\n",
    "down_cntr(clk, cnt)\n",
    "\n",
    "# Simulate it.\n",
    "waveforms = do_trans(step_time=0.01@u_ns, end_time=30@u_ns)\n",
    "oscope(waveforms, clk, *cnt, vdd_ps)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the waveforms, it's obvious the counter is decrementing: 7, 6, 5, ..., 0, 7, ... so chalk this one up as a win. But how does this compare to the counter I previously built using just an adder?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With regards to energy consumption, this ALU-based counter is about 2x worse (7 pJ compared to 3.3 pJ):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:58:47.552232Z",
     "start_time": "2021-04-30T19:58:47.507716Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total energy = 7.008028453275829e-12 J\n"
     ]
    }
   ],
   "source": [
    "time_steps = waveforms.time[1:] - waveforms.time[0:-1]\n",
    "ps_current = -waveforms[node(vdd_ps)][0:-1] # Mult by -1 to get current FROM the + terminal of the supply.\n",
    "ps_voltage = waveforms[node(vdd)][0:-1]\n",
    "\n",
    "energy = sum(ps_current * ps_voltage * time_steps)@u_J\n",
    "print(f\"Total energy = {energy}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And it uses about 2.5x the number of transistors (402 versus 162):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-30T19:58:47.573624Z",
     "start_time": "2021-04-30T19:58:47.555325Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V: 1\n",
      "PULSEV: 1\n",
      "sky130_fd_pr__pfet_01v8: 201\n",
      "sky130_fd_pr__nfet_01v8: 201\n"
     ]
    }
   ],
   "source": [
    "how_big()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## End of the Line"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "OK, well that was fun.\n",
    "\n",
    "I've gone from extracting a few transistors from the Skywater PDK all the way to constructing an ALU. And I've encapsulated that journey in this notebook so you can do it, too.\n",
    "\n",
    "Is this the way to go about using the PDK? Possibly, if you need some detailed performance measurements on some portion of your design. But for big digital designs, definitely not. Running this entire notebook takes 8 minutes and all of the designs are under 500 transistors. Using an HDL and a digital simulator would be much faster.\n",
    "\n",
    "Now for analog designs ... maybe. SPICE lends itself to the analog domain. And I can envision using some of the functions in [`scipy.optimize`](https://docs.scipy.org/doc/scipy/reference/optimize.html) to fine-tune analog circuits for certain performance criteria. But I haven't produced a concrete example of doing this so it remains in the realm of the imaginary. For now.\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.9"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {
    "height": "286px",
    "width": "296px"
   },
   "number_sections": false,
   "sideBar": false,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": true,
   "toc_position": {
    "height": "344px",
    "left": "31px",
    "top": "110.094px",
    "width": "343px"
   },
   "toc_section_display": false,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
